
ВНИМАНИЕ. Более подробно см. Запись прошивки Android с карты Product Процесс программирования устройства с помощью SD-карты Попытаемся выяснить в деталях: что конкретно происходит, когда записанная в режиме Product карта вставлена в устройство и подано питание ? Из приведеннной выше структуры прошивочной карты следует, что если прочитать раздел ENV
по его адресу в GPT, то мы получим в самом его начале содержимое общего заголовка imagewty-образа.
Вероятно, механизм программирования ("прошивания") внутренней eMMC-памяти заключается в извлечении нужных файлов из imagewty-образа, записанного на карту, и копирования их в соответствующие разделы на внутренней памяти устройства. И эти операции должен уметь выполнять один из вторичных загрузчиков: eGON, в качестве которого служит boot0, или загрузчик U-Boot. При этом где-то должен быть указан признак того, что нужно выполнять именно процедуру копирования в eMMC, а не обычную загрузку. Какой именно загрузчик используется - пока вопрос открытый (спойлер: это U-Boot). Анализ структуры начала прошивочной (Product)карты показывает, что оно практически не отличается от аналогичного места на загрузочной (StartUp) карты: есть таблица разделов (GPT), первая часть вторичного загрузчика (boot0), блоб package (дерево устройств DTB и вторичный загрузчик U-Boot) - всё на месте. Хотя из-за затертого раздела ENV отсутствуют переменные окружения, который должны содержать командные строки, необходимые для "продолжения банкета", но они требуются только для загрузки boot - "ядра", а точнее - Android Boot Image (образа загрузки Android). А учитывая, что раздел boot фактически отсутствует (он есть, но тоже затерт), то дальше и загружать нечего. Это означает, что при подаче питания на устройство с такой вставленной прошивочной картой в принципе может (и должен) начаться обычный процесс загрузки, который завершится запуском U-Boot с переходом в его командный режим (по пробелу в терминале на последовательном порте) или каким-то автоматическим продолжением (каким ?). В случае с загрузочной (StartUp) картой при автоматическом продолжении загрузки
U-Boot загружает ядро boot, выполняя содержащуюся в ENV командную строку: Но из-за отсутствия на своем месте переменных ENV загрузчик U-Boot этого, естественно, сделать не сможет. Поэтому продолжение будет другим, а именно, произойдет переход к программированию (или "прошиванию") внутренней eMMC-памяти данными, содержащимися на карте в файле imagewty-образа. Это означает, что необходимый функционал программирования либо реализован в самом U-Boot, либо U-Boot должен извлекать и запускать соответствующую программу непосредственно из imagewty-образа. 5. Для того, чтобы узнать, какой из загрузчиков занимается программированием, проведем простой эксперимент. Один и тот же imagewty-образ запишем на две разных карточки: первая в режиме StartUp, вторая - Product. И посмотрим в терминале через последовательный порт лог загрузки в обоих вариантах. Анализ и сравнение логов показывает, что в обоих вариантах записанной карты логи загрузчика Boot0 полностью совпадают. Более того, в обоих вариантах происходит запуск вторичного загрузчика U-Boot, о чём свидетельствуют строки лога: Из логов видно, что после настроек памяти и контроллера питания дальнейшая работа U-Boot определяется параметром workmode (т.е. режим работы): Кроме того, в логе с картой Product обнаруживаются такие строки с чистосердечными признаниями загрузчика U-Boot: 6. Таким образом, можно сделать однозначный вывод о том, что процедуру программирования внутренней eMMC-памяти с записанного на карту образа выполняет вторичный загрузчик U-Boot. Теперь остался вопрос: каким образом, по каким признакам U-Boot определяет, что нужно работать в режиме Product ? Где он находит это значение workmode = 17? Ниже будет показано, что секрет разного поведения загрузчика U-Boot в режимах Product и StartUp заключается всего в двух(!) байтах его заголовка. Адрес Startup Product 0x0c 0xc3 0xd4 0xe0 0x00 0x11 Причем значения этих байтов для режима StartUp совпадают с их значениями в исходном файле U-Boot IMAGEWTY-образа, то есть по умолчанию блоб U-Boot скомпилирован для загрузочного варианта StartUp, а для режима Product эти два байта модифицирует утилита PhoenixCard. Точный смысл этих двух байтов пока не ясен, но предварительно можно предположить, что один из них - это флаг или признак режима работы. А второй может оказаться просто частью изменившейся контрольной суммы. После долгих, трудных и сложных вычислений удалось выяснить, что Hex-число 0x11 - это десятичное 17. 0x11 = 17Бинго ! Ведь workmode = 17 (см. чуть выше) это и есть режим работы U-Boot в Product. А что же со вторым измененным байтом ?
0xd4 - 0xc3 = 0x11 Получается, что разница в значении байта по адресу 0x0c совпадает с изменением значения в байте режима работы (адрес = 0xe0), а это означает что в этом байте хранится младшая часть 32-разрядной контрольной суммы, которая вычисляется как простая сумма всех байтов блоба (т.е. это не CRC32). Значит наше предположение о контрольной сумме подтвердилось. Четыре байта в заголовке U-Boot (с 12-го по 15-й) представляют собой контрольную сумму 0x724440с3 или 0x724440d4 Таким образом, байт по адресу 0xe0 в заголовке блоба U-Boot устанавливает режим его работы: Startup или Product И теперь можно утверждать, что установка одного из флажков Startup или Product в интерфейсе утилиты PhoenixCard всего-навсего изменяет два бита(!) в блобе U-Boot, который и делает потом всю работу по программированию ("прошиванию") устройства с карточки. Естественно, такой U-Boot должен быть собран под специфику образов IMAGEWTY для Allwinner и уметь с ним разбираться (распаковывать, разбирать super и т.д.). Видимо, по этой причине в OpiZero2 и ТВ-боксах используется исключительно одна и та же сборка U-Boot версии "U-Boot 2018.05 Allwinner Technology" для образов Android. Вполне вероятно, что способы прошивания устройств с Allwinner через USB-кабель с помощью утилиты Phoenix Suite (или аналогичных) также основаны на функционале U-Boot. Возможно, что работает такой механизм: Phoenix извлекает из файла imagewty-образа и записывает (по протоколу FEX-FEL) в память устройства блобы вторичного загрузчика Boot0 и U-Boot (U-Boot - в пакете с другими компонентами), который стартует и выполняет всю остальную работу по программированию (так же, как и в варианте с SD-картой). Но об этом - в следующий раз... |
![]() |