Найти в Дзене
mamaich

Как редактировать раздел misc на Яндекс Модуле 2

Ранее я привел модифицированную строку запуска Андроид на Яндекс Модуле 2, которую u-boot выполняет при каждом включении устройства. Однако, записать раздел misc на Модуле 2 не так просто, как ранее делалось на Яндекс Стации Макс без пароля на USB. Модули 2 идут с паролем сразу с завода, а у нас от пароля есть только хеш. Так как у нас рут, да еще и с легко отключаемым SeLinux, то мы можем скопировать содержимое раздела misc в файл просто командой dd: Считать misc: dd if=/dev/block/misc of=/data/local/tmp/misc После чего забираем и редактируем файл на ПК, потом записываем misc назад: dd if=/data/local/tmp/misc of=/dev/block/misc Резервную копию раздела misc можно не делать, так как если записанная в нем неудачная команда приведет к бутлупу - то он очищается при сбросе к заводским настройкам (5 секунд держать нажатой лампочку при включении). А если остается возможность загрузиться в операционную систему, то misc достаточно просто забить нулями: cat /dev/zero >/dev/block/misc
Это я опис

Ранее я привел модифицированную строку запуска Андроид на Яндекс Модуле 2, которую u-boot выполняет при каждом включении устройства. Однако, записать раздел misc на Модуле 2 не так просто, как ранее делалось на Яндекс Стации Макс без пароля на USB. Модули 2 идут с паролем сразу с завода, а у нас от пароля есть только хеш.

Так как у нас рут, да еще и с легко отключаемым SeLinux, то мы можем скопировать содержимое раздела misc в файл просто командой dd:

Считать misc:

dd if=/dev/block/misc of=/data/local/tmp/misc

После чего забираем и редактируем файл на ПК, потом записываем misc назад:

dd if=/data/local/tmp/misc of=/dev/block/misc

Резервную копию раздела misc можно не делать, так как если записанная в нем неудачная команда приведет к бутлупу - то он очищается при сбросе к заводским настройкам (5 секунд держать нажатой лампочку при включении). А если остается возможность загрузиться в операционную систему, то misc достаточно просто забить нулями:

cat /dev/zero >/dev/block/misc


Это я описал простой способ.
Ниже я опишу свои приключения с другим способом работы с разделами - через утилиту update, как это делалось на Станции Макс. Всё оказалось не тривиально, но, возможно, кому-нибудь мой ход мыслей покажется интересным.

Как я ранее описывал, у нас есть возможность загрузки в интерактивный режим u-boot командой "go 0x77DB425C". Далее, если из этого режима исполнить команду "update", то устройство переключится в режим v2_usb_tool (протокол optimus, желающие могут посмотреть в исходниках u-boot).

Так как требуется переключать OTG с загрузки с USB флешки (на ней в файле s905_autoscript записана команда "go 0x77DB425C")

-2

в режим USB девайса путем выдергивания одного USB провода и вставления другого, то на Модуль 2 требуется подавать внешнее питание, чтобы при этом его не обесточить. Я поступаю так:

-3

на плате с названием "Разъем Type-C папа+мама USB3.1 с платой для распайки 24 вывода" на GND и VCC подаю землю и +5В с источника питания, и включаю либо флешку, либо через белый провод подключаю к ПК.

Итак, выдергиваем кабель с флешкой, вставляем белый провод, идущий к ПК, выполняем команду "update", и на консоли видим:

-4

На ПК определилось знакомое устройство "WorldCup Device".
Запускаем на ПК тестовую команду "update.exe bulkcmd help" - и получаем ошибку "no command at all":

-5

и такая реакция на любые строки, передаваемые в команде bulkcmd.
Очень похоже, что тут покопался кролик ("Rabbit hole activated:").

А что если выполнить другую команду? Например, команду "update.exe identify 7", которой проверяется есть ли пароль на USB или нет.
Команда - исполняется, и показывает что пароля у нас нет (оно и понятно - в протоколе optimus в u-boot проверка пароля просто не реализована):

-6

А если после нее выполнить команду

update.exe bulkcmd "store disprotect key"

то она выполнится, но только со второй попытки:

-7

То что команда стала выполняться - радует, но что со второй попытки - настораживает.

Пробуем прочитать раздел misc:

-8

опять ошибка, на этот раз странная: "write back size 0x10000 > max size 0x0". Почему-то максимальный размер буфера стал вдруг нулевым. Пора взяться за исходники.

Строка "write back size 0x" находится в файле optimus_buffer_manager.c,

-9

и даже номер строки совпал (L139).

Если посмотреть определение _bufManager, то видим, что значение .transferBufSz должно быть не нулевое:

#define OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ   (0X20<<20)//32M
#define OPTIMUS_DOWNLOAD_TRANSFER_BUF_TOTALSZ (0X20<<20)//32M

то есть, похоже, что какий-то buffer overrun затер нам данную структуру нулями. Почему он возник - скорее всего кролик должен был что-то инициализировать, а так как кролика я перепрыгнул и инициализации не произошло, то теперь какой-то указатель стал указывать немного не туда.

На помощь тут приходит дамп всей оперативной памяти устройства, которую я когда-то сделал из u-boot командами "usb write":

-11

Рекомендую статью I hack, U-Boot - там описаны другие подобные методы исследования устройства через u-boot.

Сперва требуется найти адрес структуры _bufManager. Для этого ищем в памяти упомянутую выше строку "write back size 0x":

-12

Ищем адреса после 0x7700000, там находится исполняемый код и данные u-boot (в начале памяти есть еще одна копия u-boot, которая может быть просто альтернативным отображением этих же адресов в память, либо копией, использовавшейся при расшифровке).

На найденную строку есть один cross reference:

-13

чуть выше мы видим сравнение - это и есть "if (_bufManager.transferBufSz < writeBackUnitSz ....)" из исходников. То есть, мы нашли указатель на _bufManager.transferBufSz:

0x2000000 == 32 mb
0x2000000 == 32 mb

В моем старом дампе значения правильные (не ноль, а 32 мб как и должно быть, а перед ним указатель на буфер). А если посмотреть эти же адреса сейчас через update.exe? Только надо захватить несколько дополнительных байтов спереди:

-15

Опа, это же наш "store disprotect key". И эта строка затерла нам все что после 77EA3F70.

А что за указатель 77EA3F60, в который нам написали?

-16

На него тоже есть один xref:

-17

Строка ID[..] что-то очень напоминает:

-18

Это же код, который выполняется при "update identify 7" - на консоль при этом выводилась строка "ID[16]".

Другими словами, _pcd->buf в самом начале после переключения в режим "update" указывает в непонятную область памяти, возможно, недоступную на запись, из-за чего "update bulkcmd xxx" не выполняет команды. После того, как мы делаем команду "update identify 7" этот указатель начинает указывать на небольшой буфер id[4], и команды "update bulkcmd xxx" начинают работать, но затирают собой идущую сразу после id[4] структуру _bufManager.

Я не стал разбираться где именно ломается указатель _pcd->buf, а просто восстанавливаю нужные мне байты в структуре _bufManager:

update.exe identify 7
update.exe bulkcmd "md.b 77EA3F50"
update.exe bulkcmd "md.b 77EA3F50"
update.exe bulkcmd "mw.b 77ea3f72 40 1"
update.exe bulkcmd "mw.b 77ea3f73 01 1"
update.exe bulkcmd "mw.b 77ea3f7b 02 1"
update.exe bulkcmd "mw.b 77ea3f7e 01 1"
update.exe bulkcmd "mw.b 77ea3f82 01 1"

Эти команды надо выполнять сразу после команды "update" в u-boot. После этого начинает работать:

update mread store misc normal 0x100000 misc.img
update mwrite misc.img store misc normal

как ранее я описывал в статье про Станцию Макс:

-19