Статьи

Что нужно знать об образах загрузки и восстановления Android

Эта статья была первоначально опубликована в Инженерном блоге TextNow.

Чтобы полностью понять роль, которую играют образы загрузки и восстановления Android, нам сначала необходимо понять общий процесс загрузки телефона Android. В то время как встроенное программное обеспечение больше не является частью моей повседневной работы в TextNow, я имел обыкновение носить шляпу встроенного инженера на одной из моих предыдущих работ, и я в свободное время балуюсь встроенной электроникой, поэтому я хорошо знаком с современные процедуры загрузки микропроцессора. Я должен предупредить вас, что это очень техническая статья, но, надеюсь, она будет полезна для тех, кто ищет справочный материал о том, как все это сочетается, со ссылками на то, где можно углубиться в подробности, если это необходимо. Этот тип поста был бы очень полезен, когда я изучал его ?

Процесс загрузки Android

Когда питание и сброс применяются к процессору, он просыпается и должен выяснить, что делать. В современных процессорах обычно имеется очень маленькая программа, встроенная в процессор, функция которой заключается в проверке целостности следующего компонента. Этот первый компонент иногда называют защищенным загрузочным ПЗУ, и его задача состоит в том, чтобы гарантировать, что следующий загружаемый компонент является доверенным, проверенным программным обеспечением. Это предотвращает нежелательное вмешательство системного программного обеспечения и, как таковое, повышает безопасность устройства. Проверка обычно включает в себя какое-то криптографическое шифрование с использованием схемы открытого / закрытого ключа, при этом закрытый ключ обычно хранится в секрете производителем. Примечание: обычно публичная клавиша запрограммирована во время сборки производителем телефона, и ее содержание никогда не может быть изменено, что требует, чтобы процессор всегда выполнял назначенный загрузчик, а частный аналог открытого ключа сгорал во время сборки.

Следующий компонент, загружаемый защищенным загрузочным ПЗУ, — это то, что люди обычно называют загрузчиком . Загрузчик, как я уже упоминал, обычно подписывается закрытым ключом производителя телефона и выполняет несколько заданий:

1. Загрузите загрузочный образ из энергонезависимой памяти (обычно это NAND flash) в энергозависимую память (RAM) и запустите его.

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

3. Предоставьте возможность прошивать новые загрузочные и другие образы в энергонезависимую память для будущих обновлений и восстановления после сбоя.

4. Выведите на экран какую-либо информацию и при необходимости предоставьте интерфейс для взаимодействия с пользователем. Это обычно называют режимом быстрой загрузки на некоторых устройствах Motorola, Google и других производителей.

Загрузочные образы Android

Теперь мы подошли к последнему компоненту boot-upprocess — загрузке загрузочного или восстановительного образа в RAM и его запуску.

Технически говоря, между загрузочными и восстановительными образами нет структурных различий. Разница лишь в том, какое ядро ​​и какой начальный ramdisk загружены, но они упакованы одинаково. Мы вернемся к тому, как они упакованы для создания аккуратного и аккуратного загрузочного образа.

В запуске образа загрузки есть несколько подэтапов:

1. Криптографическая проверка

2. Загрузка ядра (Linux) по нужному адресу памяти.

3. Загрузка начального виртуального диска по нужному адресу памяти.

4. Перейти на начальный адрес ядра

Криптографическая проверка обычно зависит от производителя, и, как правило, очень трудно провести обратный инжиниринг этого метода, хотя это невозможно — это было сделано ранее для определенных телефонов (например, для старых телефонов LG эпохи Kit-Kat).

Ядро — это сердце операционной системы, поскольку оно использует постоянный пульс прерываний и событий, которые поддерживают работу современной операционной системы. Эта магия имеет очень скудное происхождение как простые байки, которые были скомпилированы таким образом, чтобы проснуться и начать работать с определенного адреса памяти. Этот адрес варьируется в зависимости от конкретного телефона и расположения памяти. Как только выполнение начнется, ядро ​​начнет загрузку драйверов и настроит более продвинутые средства, чтобы оно могло запускать некоторые из своих собственных программ.

Само по себе ядро ​​не будет знать, что делать после загрузки. Сидел бы там и ничего не делал. Но то, что ожидает Linuxkernel, это начальный виртуальный диск с предопределенным адресом памяти. Этот виртуальный диск содержит очень элементарную и обычно доступную только для чтения файловую систему, которая содержит самую простую корневую файловую систему из возможных, и файл под / sbin / init, который ядро ​​выполняет как последний элемент, выполняемый при инициализации. Эта в этом   программы запускают некоторые сценарии, которые запускают другие программы, взаимодействующие друг с другом и, наконец, предоставляют все возможности системы.

Итак, теперь мы возвращаемся к разнице между aboot и образом восстановления. В то время как ядро ​​иногда совпадает с загрузочным изображением, виртуальный диск образа восстановления имеет различные наборы сценариев инициализации, которые не запускают Java VM, а вместо этого запускают небольшую программу на языке C, называемую (как вы думаете, это восстановление ). Восстановление отображает ограниченный пользовательский интерфейс, который позволяет пользователю запускать систему, выполнять сброс настроек, очищать раздел кэша и т. Д. Некоторые пользовательские восстановления имеют собственную программу, которая предлагает еще больше функциональных возможностей.

Упаковка загрузочного образа Android

Загрузочные образы Android имеют специфическая структура, внутренняя организация которой отражает память, в которой она находится, а именно флэш. Flash — это определенный тип памяти, который не имеет произвольного доступа, но читается на страницах, размеры которых варьируются в зависимости от конкретной микросхемы, часто в диапазоне 4 Кбайт. По этой причине компоненты загрузочного образа выровнены по размеру страницы, поэтому загрузка более эффективна (помимо прочего, я не буду здесь вдаваться в подробности). Структура загрузочного образа показана на рисунке ниже:

Макет загрузочного образа Android

Я должен упомянуть кое-что об этом втором этапе. Честно говоря, я не знаю его смысла , теоретического намерения этого. Я видел, как это использовалось в более недавние времена для хранения блока дерева устройств ядра (DTB, еще одна длинная и глубоко техническая тема, которую не объяснили в других местах) некоторыми производителями телефонов. В старых ядрах в качестве образа ядра использовалась DTB, а теперь они разделены на отдельные части, чтобы упростить создание более общего ядра, которое можно адаптировать к различным аппаратным конфигурациям в рамках одной и той же архитектуры.

Быстро перемещаясь вдоль (и обратно!) К заголовку загрузочного образа, это в первую очередь говорит загрузчику, как загружать компоненты образа загрузки, и это выглядит примерно так:

Заголовок загрузочного образа Android

Как вы можете видеть, в нем есть несколько полей «учета» о том, насколько велики другие подкомпоненты загрузочного образа, в какой адрес их загружать и т. Д.

У этого также есть область, названная волшебством . Themagic field — это просто строка известных символов, идентифицирующих это как загрузочный образ Android. В этом случае строка «ANDROID!», Которая умещается в 8 байтов.

Кто-то, знакомый с процессом загрузки и запуска ядра Linux, распознает теги ядра и поля аргументов командной строки, как способы передачи в ядро ​​дополнительной пользовательской информации, например, где должна быть консоль и где найти исходный виртуальный диск, откуда загружать программу init. ,

Работа с загрузочными изображениями Android

Итак, поскольку у нас есть пользовательские образы восстановления и загрузки для наших телефонов Android (такие как TWRP, CWM и т. Д.), Очевидно, что кто-то должен был создать свой собственный образ восстановления или изменить уже существующий загрузочный образ. Большая часть работы была выполнена с использованием уже открытого кода Google Android, но там был только код для создания загрузочного образа из его компонентов. Не было инструмента для распаковки загрузочного образа для модификации. Теперь вы можете использовать такой инструмент, как https://github.com/osm0sis/mkbootimg topack и распакуйте загрузочные образы и замените ядро ​​или измените исходный диск.

Другие области для изучения

Есть несколько интересных аспектов, связанных с начальным виртуальным диском, которые применяются как к загрузочным, так и к восстановительным образам Android, которые эта статья не будет охватывать подробно из-за уже растущего размера, но о которых стоит упомянуть.

● Файловая система, которую используют начальные виртуальные диски, обычно представляет собой сжатый архив CPIO.

● Вы можете упаковать и распаковать исходные диски и изменить их

● сценарии инициализации написаны на их собственном доменном языке (DSL), и вы можете прочитать их README для получения дополнительной информации

● Контексты файла SELinux по умолчанию и политики обычно находятся в корне виртуального диска

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