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

Включаем ADB на Яндекс мини 3 про, часть 3 - делаем silent=0

В предыдущих двух статьях я описал процесс пайки и привел немного теории о содержимом NAND памяти. В этой части опишу как внести изменения в образ прошивки и подготовить его к записи на микросхему.
Примеры привожу для Мини 3 про, но аналогичный способ должен работать и на других устройствах от Яндекс, имеющих NAND (для устройств с EMMC подойдет только раздел 4). 1. Читаем дамп программатором Внимание: я настоятельно рекомендую делать дамп прошивки устройства либо непосредственно после покупки (ни разу не включая его), либо сразу после сброса до заводских настроек. В таком случае в NAND будет минимум мусора, который усложнит дальнейшие задачи. Считанный дамп NAND должен содержать в себе OOB данные - в противном случае потеряется информация, используемая при загрузке устройства. В программаторе XGecu необходимо перед чтением удостовериться, что выбрана "Include Spare Area": По умолчанию дамп прошивки Мини 3 про будет сохранен в файл с именем TC58NVG2S0HTA00@TSOP48.BIN 2. Корректируем о
Оглавление

В предыдущих двух статьях я описал процесс пайки и привел немного теории о содержимом NAND памяти. В этой части опишу как внести изменения в образ прошивки и подготовить его к записи на микросхему.
Примеры привожу для Мини 3 про, но аналогичный способ должен работать и на других устройствах от Яндекс, имеющих NAND (для устройств с EMMC подойдет только раздел 4).

1. Читаем дамп программатором

Внимание: я настоятельно рекомендую делать дамп прошивки устройства либо непосредственно после покупки (ни разу не включая его), либо сразу после сброса до заводских настроек. В таком случае в NAND будет минимум мусора, который усложнит дальнейшие задачи.

Считанный дамп NAND должен содержать в себе OOB данные - в противном случае потеряется информация, используемая при загрузке устройства. В программаторе XGecu необходимо перед чтением удостовериться, что выбрана "Include Spare Area":

По умолчанию дамп прошивки Мини 3 про будет сохранен в файл с именем TC58NVG2S0HTA00@TSOP48.BIN

2. Корректируем ошибки ECC в дампе

XGecu, в отличие от UFPI не знает какие алгоритмы коррекции ошибок используются Amlogic при работе с данной микросхемой, поэтому пришлось написать свою утилиту. Утилита кроссплатформенная, исходники можно собрать под любой Linux, так же на странице releases выложен бинарник под Windows.

Для корректировки ошибок запускаем в консоли команду:

ecc_fix -4 fixdata TC58NVG2S0HTA00@TSOP48.BIN TC58NVG2S0HTA00@TSOP48-fixed.bin

Первый параметр - размер страницы (у нас 4352 байта), второй - команда fixdata, третий - файл с дампом, считанным программатором. Последний параметр - файл с исправленными данными.

На этот раз приведу скриншот Windows версии утилиты:

Как видите, большое количество блоков с ошибками - это норма. Но если вы получили больше сотни тысяч ошибок - проверьте корректность указания размера страницы (параметр -2 или -4), либо эти утилиты просто не для вашего NAND и дальше статью читать не стоит.

На выходе получаем файл TC58NVG2S0HTA00@TSOP48-fixed.bin

В Мини 3 про (pickle) и Яндекс Станции 2 (midi) размер страницы 4352 байт, в Лайтах - 2176 байт.

3. Очищаем дамп от OOB данных

Перед тем как приступить к внесению изменений, необходимо исправленный файл очистить от out of band данных, оставив в нем только полезные. Делается это еще одной кроссплатформенной утилитой, Windows версию которой я тоже выложил.

Запускаем в консоли команду:

file_skip -4 TC58NVG2S0HTA00@TSOP48-fixed.bin out.bin

Первый параметр - размер страницы (4352 байта), второй - файл исправленного в пункте 2 дампа, третий параметр - имя очищенного файла.

-3

Получаем файл out.bin, очищенный от вспомогательных данных.

4. Включаем silent=0

Самой первой операцией, которая открывает дорогу для дальнейшего анализа прошивки, является установка silent=0 в u-boot environment. Тем самым на консоли UART мы увидим дополнительную информацию, в частности, адреса разделов NAND. А в случае диагностики незагружающихся устройств - вывод может пролить свет на причину перезагрузки/зависания.

Сперва необходимо найти начало u-boot environment в очищенном дампе. Я обычно делаю это грубым поиском строки "bootcmd=".

на всякий случай я стер свой серийник
на всякий случай я стер свой серийник

Напомню формат environment - сперва идут 4 байта CRC32, затем разделённые нулевыми байтами строки вида "имя=значение". Завершает список два идущих подряд нулевых байта. Полный размер environment обычно 64 Кб (4 байта CRC32+65532 байта данных дополненных до 64 Кб нулями).

То есть, найдя строку "bootcmd=" требуется пролистать назад на один-два сектора до контрольной суммы. Обычно перед ней идет блок из байтов со значением 0xFF или 0x00, а ее адрес выровнен на границу в 0x10000 байт (но, кажется, я встречал и выравненные на 0x8000).

Блоков environment в NAND может быть несколько копий. Например, в том дампе, который сейчас передо мной их 7 штук. Именно поэтому я рекомендую делать дамп до первого включения свежеприобретенного устройства - даже при неуспешной загрузке u-boot обновляет environment, записывая его в новое место, а чем больше копий - тем больше однотипных действий нам потребуется сделать далее.

Для дальнейшей модификации нам требуется выписать адреса всех копий environment. В моем случае это были: 00600000, 00610000, 00620000, 00630000, 00640000, 00650000, 00660000. Как видите, адреса кратны 64 кб, хотя между ними могут быть пропуски. А если учесть, что под environment зарезервировано 8 erase блоков по 256 кб, то в худшем случае можно столкнуться с 32 копиями env.

Для установки silent=0 следует взять одну из копий (лучше всего последнюю или самую длинную) и сохранить её в файл. Далее изменяем в 16-ричном редакторе сохраненную копию, исправляя в ней silent=1 на silent=0:

-5

После чего обновляем CRC32 в начале отредактированного файла специально написанной для этого Grok-ом утилитой:

python fixcrc_uboot_env.py env
-6

Если утилите передать файл размером менее 65536 байт - то она сама дополнит его нулями до требуемых 65536.

Далее следует модифицированный файл env записать в out.bin по всем смещениям, где находились оригинальные копии environment. В моем случае это 00600000, 00610000, 00620000, 00630000, 00640000, 00650000, 00660000.
Я использую утилиту
hiew32, но подойдет и любой другой hex редактор или самодельный скрипт.

-7

5. Восстанавливаем OOB данные для модифицированного файла

Теперь необходимо из модифицированного очищенного дампа получить полный, включающий в себя OOB. Просто посчитать и добавить к каждому сектору ECC блоки мы не можем - так как системные сектора, а так же сектора файловой системы UBIFS содержат в OOB служебную информацию, а не BCH код.

Я (конечно же не без помощи ИИ) сделал утилиту file_combine, которая вносит изменения в оригинальный дамп и специальным образом помечает в нем отредактированные нами сектора, оставляя остальные без изменений. Её код также лежит на github. Скомпилированные бинарники для Windows лежат там же.

Используем утилиту так:

file_combine -4 TC58NVG2S0HTA00@TSOP48-fixed.bin out.bin TC58NVG2S0HTA00@TSOP48-edited.bin

Первый параметр - размер страницы, второй - оригинальный дамп из п.3, третий - отредактированный в п.4 файл out.bin, четвертый - выходной файл, для которого необходимо далее пересчитать ECC.

С помощью уже упомянутой в п.2 утилиты ecc_fix пересчитываем ECC в модифицированных секторах:

ecc_fix -4 fixecc TC58NVG2S0HTA00@TSOP48-edited.bin TC58NVG2S0HTA00@TSOP48-towrite.bin

Первый параметр - как обычно, размер страницы. Второй - команда fixecc, третий - имя созданного утилитой file_combine выходного файла, четвертый - файл, который будем записывать в NAND:

-8

Возможно, в будущем я объединю утилиты в одну - но пока что использую их так.

6. Пишем отредактированный файл в NAND

Здесь всё очень просто. Загружаем в Xgpro полученный в конце п.5 файл TC58NVG2S0HTA00@TSOP48-towrite.bin и записываем его на микросхему:

дожидаться окончания verify не обязательно, я обычно верификацию прерываю
дожидаться окончания verify не обязательно, я обычно верификацию прерываю

Если записываете на неоригинальную микросхему - необходимо подобрать такую, у которой bad блоки будут выпадать на вторую половину ближе к концу (то есть на раздел /data, там UBIFS, который достаточно хорошо работает с бэдами) или на неиспользуемые области в конце или между разделами. Утилиту для работы с BBT я не делал (да и не планирую, я для тестов купил 5 микросхем, из которых 2 мне подошли). Но функционал пересчета BBT есть в UFPI.

После записи, в UART видим подробный лог загрузки:

-10

Инструкция по включению ADB будет в следующей, надеюсь финальной, части.