1. Эксперимент по замене ядра на TWRPВ любом устройстве на базе Android имеется рекавери (Recоvery), которое представляет собой простейшую операционную систему, предназначенную для сервисных и отладочных целей. Очень часто стандартное рекавери, имеющее достаточно примитивный интерфейс и очень ограниченный функционал, заменяют на так называемое "кастомное рекавери", обычно это TWRP (по имени проекта). Такая замена выполняется путем записи образа TWRP в раздел Recovery загрузочного носителя устройства, при этом стандартный рекавери, естественно, уничтожается. Возникает вопрос: а нельзя ли сделать так, чтобы в устройстве было два рекавери: стандартное и TWRP ? То есть изменить логику: OR ( ИЛИ ) на AND ( И ). Если это осуществимо, то появляется возможность повысить надежность и живучесть устройства, особенно в тех случаях, когда работоспособность TWRP не гарантирована и требует проверки на реальном устройстве. Для ответа на этот вопрос был проведен эксперимент на устройстве OrangePi Zero 2, являющемся прототипом многих ТВ-боксов, использующих SoC Allwinner H616 (поэтому описанные ниже результаты вполне применимы к любому аналогичному ТВ-боксу). После распаковки утилитой imgrepacker.exe стокового образа Android (версии V1.1) образуется папка с именем IMG.DUMP, содержащая набор файлов, участвующих в записи прошивки на карту памяти. Теперь удаляем в этой папке файл образа ядра boot.fex, а вместо него записываем образ кастомного рекавери TWRP. Это файла twrp.img, но переименованный в boot.fex. Остальные файлы остаются без изменения. После этого делаем утилитой imgrepacker.exe обратную упаковку этой папки в файл прошивочного образа с именем test.img. Затем записываем утилитой PhoenixCard этот файл на SD-карту в режиме startup и включаем питание устройства со вставленной картой. В результате наблюдаем на экране монитора загрузку операционной системы, которая представляет собой не что иное, как TWRP. Это означает, что простой заменой одного файла в образе прошивки достигается загрузка TWRP в качестве операционной системы. Но обычное при этом стандартное рекавери тоже осталось на своем месте, т.е. в разделе Recovery. Чтобы в этом убедиться, достаточно выполнить команду его загрузки, находясь в интерфейсе TWRP: "Перезагрузка -> Рекавери". Для управления используется мышка. После произошедшей перезагрузки на экране монитора наблюдается интерфейс обычного стандартного рекавери. Здесь мышкой управлять сложно, удобнее стрелками физической клавиатуры (или ИК-пульта, если к устройству подключен ИК-приемник). Теперь для обратного перехода в TWRP достаточно в этом рекавери выполнить команду: "Reboot system now". Проведенный эксперимент показал, что загрузчик U-Boot может в автоматическом режиме (без вмешательства в его работу по UART) выполнять загрузку системы из двух разделов: При этом он не проверяет содержимое раздела boot (или recovery), а просто загржает его в память и стартует. Для того, чтобы убедиться в этом, проверим процесс загрузки в ручном режиме. Если в момент старта U-Bоот нажать пробел, то мы попадаем в командный интерфейс U-Bоот. В котором можно выполнять загрузку системы вручную командами его интерфейса. Как их узнать ? Если посмотреть содержимое массива переменных окружения Env, то мы увидим все нужные нам команды загрузки: Hit any key to stop autoboot: 0
Здесь видно, что сачала содержимое раздела boot (или recavery) загружается в оперативную память по адресу 0x45000000 командой sunxi_flash read sunxi_flash read 45000000 boot А затем выполняется команда bootm - загрузка образа из памяти. bootm 45000000 Таким образом, находясь в командном интерфейсе U-Boot, можно вручную загрузить образ из 2-х разделов: Более того, можно предполжить, что если добавить таблицу разделов GPT новый раздел (например, с именем twrp), и записать в него (любым способом) содержимое файла twrp.img, то мы получим образ с тремя загрузочными разделами, позволяющий по выбору загружать одну из трех систем:
Для проверки этой идеи попробуем создать на основе стандартной версии прошивки Андроид V1.1 модифицированный образ прошивки, в который добавлен файл рекавери TWRP.fex, а также сделаны необходимые изменения для сохранения возможности записи этого образа c использованием утилиты PhoenixCard. 2. Образ с тремя загрузочными разделамиДля создания такого образа этого требуется модифицировать четыре файла в исходном образе прошивки: Отметим, что на самом деле, на карту памяти (в её начало) записывается лишь один GPT, а остальные файлы нужны только для нормальной работы утилиты-прошивальщика PhoenixCard. При этом исходный текстовый файл sys_partition.fex, хотя и присутствует в пакете образа прошивки img, но реально он этой утилитой не используется, а нужен для создания из него трех остальных бинарных файлов с помощью специального софта под Linux или Windows. В нашем случае для этих целей пришлось написать специальный конвертор, поскольку найденные утилиты (типа update_mbr) работать не захотели из-за какой-то несовместимости, проще было написать свой софт, чем с ними разбираться. Измененный текстовый файл конфигурации разделов выглядит так: sys_partition.fex Этот файл представляет собой список создаваемых разделов (имя и размер), с указанием имён записываемых в них файлов. Все четыре измененных файла лежат в архиве: Измененные файлы Итак, все подготовительные операции проделаны, нужные файлы скопированы в папку test.img.dump (с заменой прежних версий), а также в эту папку добавлен файл кастомного рекавери twrp.fex. Теперь утилитой imgrepacker упаковываем эту папку и получаем новый обрах test.img. Осталось только записать его на карту памяти утилитой PhoenixCard. Утилита восприняла этот образ как родной, извлекла из него нужную для себя информацию, сохранив её во временных файлах, и начала запись на SD-картe. Процесс начался весело, успешно записались GPT и несколько основных разделов (и даже super), но потом что-то пошло не так, утилита споткнулась на разделе recovery, выдала ошибку 2204 и остановилась. Разбираться с причинами появления ошибки в PhoenixCard мне не захотелось. Сложность в том, что это не обычная утилита, имеющая открытый исходный текст, а некий винегрет из программ (написанных на разных языках и в разное время ), а также служебных и вспомогательных файлов. Да, что-то ей не понравилось в этом собранном образе. Но на карточке нормально создана таблица разделов GPT и в основные разделы нормально записана информация, достаточная для первой загрузки и проверки работоспособности (пока без рекавери). Размер записанной карточки - 8 Gb . Для проверки можно посмотреть на неё, например, под Windows утилитой diskinternals. Видим, что d nf,kbwt все разделы на месте, в том числе добавленный раздел с именем twrp (хотя, он пока пустой, естественно, из-за ошибки, обраруженной прошивальщиком). Поэтому можно проверять эту карту непосредственно на устройстве, загрузчик должен работать. Так оно и есть: вставленная в устройство карточка нормально загружается в U-Boot и дальше - в основную систему. Для проверки таблицы разделов непосредственно на устройстве выполним консольную команду: console:/# sgdisk --print /dev/block/mmcblk0 ******************** Disk /dev/block/mmcblk0: 15523840 sectors, 7.4 GiB Logical sector size: 512 bytes Disk identifier (GUID): AB6F3888-569A-4926-9668-80941DCB40BC Partition table holds up to 20 entries First usable sector is 73728, last usable sector is 15523838 Partitions will be aligned on 1024-sector boundaries Total free space is 33 sectors (16.5 KiB) Number Start End Size Code Name (sector) (sector) 1 73728 139263 32.0 MiB 0700 bootloader 2 139264 172031 16.0 MiB 0700 env 3 172032 237567 32.0 MiB 0700 boot 4 237568 3383295 1.5 GiB 0700 super 5 3383296 3416063 16.0 MiB 0700 misc 6 3416064 3481599 32.0 MiB 0700 recovery 7 3481600 3547135 32.0 MiB 0700 twrp 8 3547136 4857855 640.0 MiB 0700 cache 9 4857856 4890623 16.0 MiB 0700 vbmeta 10 4890624 4923391 16.0 MiB 0700 vbmeta_system 11 4923392 4956159 16.0 MiB 0700 vbmeta_vendor 12 4956160 4988927 16.0 MiB 0700 metadata 13 4988928 5021695 16.0 MiB 0700 private 14 5021696 5022719 512.0 KiB 0700 frp 15 5022720 5054463 15.5 MiB 0700 empty 16 5054464 5087231 16.0 MiB 0700 media_data 17 5087232 5119999 16.0 MiB 0700 Reserve0 18 5120000 15523805 5.0 GiB 0700 UDISK Примечание. При этом sgdisk почему-то грозно ругается на ошибку контрольной суммы CRC32. Warning! Error 2 reading partition table for CRC check! Warning! One or more CRCs don't match. You should repair the disk! Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk verification and recovery are STRONGLY recommended. Однако на стоковой прошивке (т.е. с оригинальным GPT) sgdisk выдает аналогичные предупреждения, что свидетельствует о его некоей несовместимости с данным GPT, не влияющей на нормальное использование такой таблицы разделов. Возможно, на момент раписания утилиты sgdisk формат GPT как-то отличался. В нём есть некоторая странность с альтернативным (резервным) заголовком GPT Дальше можно без проблем записать непосредственно на работающем устройстве два образа рекавери в соответствующие разделы с помощью консольных команд dd или с помощью fasboot. Для этого скопируем на ПК два файла recovery.fex и twrp.fex на USB-флешку и вставим её в наше устройство. Теперь флешка - это диск /mnt/media_rw/0000-006F/ (естественно, для другой флешки имя будет другим). Выполняем две консольные команды : dd if=/mnt/media_rw/0000-006F/recovery.fex of=/dev/block/mmcblk0p6 bs=512 count=65536 dd if=/mnt/media_rw/0000-006F/twrp.fex of=/dev/block/mmcblk0p7 bs=512 count=65536 Осталось только запустить и проверить каждое из двух рекавери. Входим в U-Boot, для этого в момент включения или перезагрузки устройства тормозим автозагрузку нажатием пробела на клавиатуре ПК, к которому подключено устройство через UART и запущен MobaXterm. Загрузка стандартного рекавери: run setargs_mmc; sunxi_flash read 45000000 recovery;bootm 45000000 Загрузка рекавери TWRP: run setargs_mmc;sunxi_flash read 45000000 twrp;bootm 45000000 Здесь три команды: Подробно о команде смотрите: bootm . Кроме того, можно записать команду загрузки twrp в переменные окружения (слеш перед ';' обязателен !) : env set boot_twrp sunxi_flash read 45000000 twrp\;bootm 45000000 env save В этом случае команда загрузки twrp становится ещё короче: run setargs_mmc;run boot_twrp Заметим, что эти приведенные выше команды демонстрируют возможности управления загрузкой с помощью простого редактирования ENV. Таким образом, для выбора и запуска нужного рекавери достаточно просто указать имя раздела, из которого требуется загрузить нужную систему. При этом имя раздела (и файла, который в него загружен) может быть любым (например, 'kakayachren'). Главное, чтобы этот раздел был прописан в таблице разделов GPT. Более того, если в такой раздел (например, с именем twrp) записать файл альтернативного ядра boot.fex (например, пропатченного магиском), то в устройстве появляется возможность выбора одного из двух (или трех) ядер boot при загрузке системы. dd if=/mnt/media_rw/0000-006F/boot.fex of=/dev/block/mmcblk0p7 bs=512 count=65536 Теперь по команде run setargs_mmc;run boot_twrp Для сравнения приведем два лога: 1. Загрузка ядра из раздела boot (здесь лежит boot от стоковой прошивки V1.1):2. Загрузка ядра из раздела twrp (в котором лежит другой boot - от Lite образа):
Cледует уточнить, что речь не идет о практической пользе или преимуществах установки на устройство одновременно двух рекавери (или двух ядер). Описанный выше эксперимент проведен лишь с целью понимания механизма загрузки и использования образов ядра и/или рекавери. Поскольку в многочисленных примерах и рекомендациях кастомное рекавери обычно ставится вместо стандартного рекавери (и в этом есть смысл из-за физических кнопок, его запускающих), что может создать не очень точное представление об особой роли этого раздела. На самом деле, можно пойти и дальше. Если добавить в таблицу разделов GPT несколько разделов размером 32 Мбайт с именами, например alpha, beta, gamma (или discC, diskD, discE) и записать в них командой dd разные образы ядра ( boot1.img, boot2.img, boot3.img), то появляется возможность выбора загружаемой системы с помощью простого редактирования командной строки в массиве переменных окружения ENV. Это можно делать двумя способами: bootcmd=run setargs_mmc boot_normal bootcmd=run setargs_mmc boot_alpha, boot_alpha=sunxi_flash read 45000000 alpha;bootm 45000000 boot_beta=sunxi_flash read 45000000 beta;bootm 45000000 boot_gamma=sunxi_flash read 45000000 gamma;bootm 45000000 Таким образом, в дополнение к основному варианту с ядром, хранящимся в разделе boot, получим ещё три альтернативных варианта загрузки системы. Вероятно, это можно использовать, например, при отладке свежеиспеченного ядра. Не исключено, что этот вариант тоже пройдет практическую проверку в недалеком будущем.... |