Переместить fastboot в пространство пользователя

Fastboot — это название модуля и режима загрузчика. Android 10 и более поздние версии поддерживают изменение размера разделов путём переноса реализации fastboot из загрузчика в пользовательское пространство. Это перемещение позволяет переместить код прошивки в общее, удобное для обслуживания и тестирования место, где только специфичные для производителя части fastboot реализуются с помощью уровня аппаратной абстракции (HAL). Кроме того, Android 12 и более поздние версии поддерживают прошивку RAM-дисков с помощью дополнительной команды fastboot.

Унифицировать быструю загрузку и восстановление

Поскольку процессы fastboot и recovery в пользовательском пространстве схожи, их можно объединить в один раздел или двоичный файл. Это даёт такие преимущества, как экономия места, меньшее количество разделов в целом и совместное использование ядра и библиотек для fastboot и recovery.

Fastbootd — это имя демона и режима пользовательского пространства. Для поддержки fastbootd загрузчик должен реализовать новую команду блока управления загрузкой (BCB) boot-fastboot . Для перехода в режим fastbootd загрузчик записывает boot-fastboot в поле команд сообщения BCB и оставляет поле recovery BCB без изменений (чтобы обеспечить возможность перезапуска любых прерванных задач восстановления). Поля status , stage и reserved также остаются без изменений. Загрузчик загружает образ восстановления, обнаружив boot-fastboot в поле команд BCB. Затем процесс восстановления анализирует сообщение BCB и переключается в режим fastbootd .

Команды ADB

В этом разделе описывается команда adb для интеграции fastbootd . Результаты команды различаются в зависимости от того, выполняется ли она системой или восстановлением.

Команда Описание
reboot fastboot
  • Перезагружается в fastbootd (систему).
  • Вход в fastbootd напрямую без перезагрузки (восстановления).

Команды быстрой загрузки

В этом разделе описаны команды fastboot для интеграции fastbootd , включая новые команды для прошивки и управления логическими разделами. Некоторые команды приводят к разным результатам в зависимости от того, были ли они выполнены загрузчиком или fastbootd .

Команда Описание
reboot recovery
  • Перезагружается в режим восстановления (загрузчика).
  • Вход в режим восстановления напрямую, без перезагрузки ( fastbootd ).
reboot fastboot Перезагружается в fastbootd .
getvar is-userspace
  • Возвращает yes ( fastbootd ).
  • Возвращает no (загрузчик).
getvar is-logical: <partition> Возвращает yes , если заданный раздел является логическим, и no в противном случае. Логические разделы поддерживают все перечисленные ниже команды.
getvar super-partition-name Возвращает имя суперраздела. Имя включает суффикс текущего слота, если суперраздел является разделом A/B (обычно это не так).
create-logical-partition <partition> <size> Создаёт логический раздел с заданным именем и размером. Логический раздел с таким именем не должен существовать.
delete-logical-partition <partition> Удаляет указанный логический раздел (фактически стирает раздел).
resize-logical-partition <partition> <size> Изменяет размер логического раздела до нового без изменения его содержимого. Завершается ошибкой, если для изменения размера недостаточно свободного места.
flash <partition> [ <filename> ] Записывает файл на флэш-диск. Устройство должно быть разблокировано.
erase <partition> Удаляет раздел (не обязательно для безопасного стирания). Устройство должно быть разблокировано.
getvar <variable> | all Отображает переменную загрузчика или все переменные. Если переменная не существует, возвращает ошибку.
set_active <slot>

Устанавливает указанный загрузочный слот A/B как active . При следующей попытке загрузки система загрузится с указанного слота.

Для поддержки A/B слоты представляют собой дублированные наборы разделов, с которых можно загружаться независимо. Слоты называются a , b и т. д. и различаются добавлением суффиксов _a , _b и т. д. к имени раздела.

reboot Перезагружает устройство в обычном режиме.
reboot-bootloader (или reboot bootloader ) Перезагружает устройство в режим загрузчика.
fastboot fetch vendor_boot <out.img>

Используется в Android 12 и выше для поддержки перепрошивки RAM-дисков поставщика.

Получает полный размер раздела и размер фрагмента. Получает данные для каждого фрагмента, а затем объединяет их в файл <out.img>

Подробности смотрите fastboot fetch vendor_boot <out.img> .

fastboot flash vendor_boot:default <vendor-ramdisk.img>

Используется в Android 12 и выше для поддержки перепрошивки RAM-дисков поставщика.

Это особый вариант команды flash. Он выполняет функцию fetch vendor_boot , как при вызове fastboot fetch . Новый образ vendor_boot который она прошивает, зависит от версии заголовка загрузки (3 или 4).

Подробности смотрите в fastboot flash vendor_boot:default <vendor-ramdisk.img> .

fastboot flash vendor_boot: <foo> <vendor-ramdisk.img> Используется в Android 12 и выше для поддержки перепрошивки RAM-дисков поставщика.

Получает образ vendor_boot . Возвращает ошибку, если заголовок загрузки vendor имеет версию 3. Если это версия 4, находит правильный фрагмент RAM-диска vendor (если доступен). Заменяет его указанным образом, пересчитывает размеры и смещения и прошивает новый vendor_boot image .

Подробности смотрите в fastboot flash vendor_boot: <foo> <vendor-ramdisk.img>

Fastboot и загрузчик

Загрузчик прошивает разделы bootloader , radio и boot/recovery , после чего устройство загружается в режиме fastboot (пользовательское пространство) и прошивает все остальные разделы. Загрузчик должен поддерживать следующие команды.

Команда Описание
download Загружает образ во флеш-память.
flash recovery <image> / flash boot <image> / flash bootloader <image> / Перепрошивка раздела recovery/boot и загрузчика.
reboot Перезагружает устройство.
reboot fastboot Перезагружается в режиме быстрой загрузки.
reboot recovery Перезагружается для восстановления.
getvar Получает переменную загрузчика, необходимую для прошивки образа восстановления/загрузки (например, current-slot и max-download-size ).
oem <command> Команда определена OEM.

Динамические разделы

Загрузчик не должен допускать перепрошивку или стирание динамических разделов и должен возвращать ошибку при попытке этих операций. Для устройств с модернизированными динамическими разделами утилита fastboot (и загрузчик) поддерживает принудительный режим для прямой перепрошивки динамического раздела в режиме загрузчика. Например, если system представляет собой динамический раздел на модернизированном устройстве, использование команды fastboot --force flash system позволяет загрузчику (вместо fastbootd ) перепрошить раздел.

Зарядка в выключенном режиме

Если устройство поддерживает зарядку в выключенном режиме или иным образом автоматически загружается в специальный режим при подаче питания, реализация команды fastboot oem off-mode-charge 0 должна обойти эти специальные режимы, чтобы устройство загружалось так, как если бы пользователь нажал кнопку питания.

Fastboot OEM HAL

Чтобы полностью заменить загрузчик fastboot, fastboot должен поддерживать все существующие команды fastboot. Многие из этих команд предоставлены OEM-производителями и документированы, но требуют собственной реализации. Многие команды, специфичные для OEM-производителей, не документированы. Для обработки таких команд HAL-уровня fastboot определяет необходимые OEM-команды. OEM-производители также могут реализовывать собственные команды.

Определение fastboot HAL следующее:

import IFastbootLogger;

/**
 * IFastboot interface implements vendor specific fastboot commands.
 */
interface IFastboot {
    /**
     * Returns a bool indicating whether the bootloader is enforcing verified
     * boot.
     *
     * @return verifiedBootState True if the bootloader is enforcing verified
     * boot and False otherwise.
     */
    isVerifiedBootEnabled() generates (bool verifiedBootState);

    /**
     * Returns a bool indicating the off-mode-charge setting. If off-mode
     * charging is enabled, the device autoboots into a special mode when
     * power is applied.
     *
     * @return offModeChargeState True if the setting is enabled and False if
     * not.
     */
    isOffModeChargeEnabled() generates (bool offModeChargeState);

    /**
     * Returns the minimum battery voltage required for flashing in mV.
     *
     * @return batteryVoltage Minimum battery voltage (in mV) required for
     * flashing to be successful.
     */
    getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage);

    /**
     * Returns the file system type of the partition. This is only required for
     * physical partitions that need to be wiped and reformatted.
     *
     * @return type Can be ext4, f2fs or raw.
     * @return result SUCCESS if the operation is successful,
     * FAILURE_UNKNOWN if the partition is invalid or does not require
     * reformatting.
     */
    getPartitionType(string partitionName) generates (FileSystemType type, Result result);

    /**
     * Executes a fastboot OEM command.
     *
     * @param oemCmd The oem command that is passed to the fastboot HAL.
     * @response result Returns the status SUCCESS if the operation is
     * successful,
     * INVALID_ARGUMENT for bad arguments,
     * FAILURE_UNKNOWN for an invalid/unsupported command.
     */
    doOemCommand(string oemCmd) generates (Result result);

};

Включить fastbootd

Чтобы включить fastbootd на устройстве:

  1. Добавьте fastbootd в PRODUCT_PACKAGES в device.mk : PRODUCT_PACKAGES += fastbootd .

  2. Убедитесь, что fastboot HAL, boot control HAL и health HAL упакованы как часть образа восстановления.

  3. Добавьте все разрешения SEPolicy, специфичные для устройства, необходимые для fastbootd . Например, fastbootd требует права на запись в раздел устройства для его прошивки. Кроме того, реализация HAL в fastboot также может потребовать специфичных для устройства разрешений.

Для проверки быстрой загрузки пользовательского пространства запустите Vendor Test Suite (VTS) .

RAM-диски от поставщика флэш-памяти

В Android 12 и более поздних версиях реализована поддержка перепрошивки RAM-дисков с помощью новой команды fastboot, которая извлекает полный образ vendor_boot с устройства. Эта команда побуждает инструмент fastboot на стороне хоста прочитать заголовок загрузки vendor, переустановить образ и прошить новый образ.

Для извлечения полного образа vendor_boot команда fetch:vendor_boot была добавлена ​​как в протокол fastboot, так и в реализацию протокола fastbootd в Android 12. Обратите внимание, что fastbootd реализует эту функцию, но сам загрузчик может её не поддерживать. OEM-производители могут добавить команду fetch:vendor_boot в свою реализацию протокола для загрузчика. Однако, если эта команда не распознаётся в режиме загрузчика, то прошивка отдельных RAM-дисков вендора в режиме загрузчика не поддерживается производителем.

Изменения загрузчика

Команды getvar:max-fetch-size и fetch:name реализованы в fastbootd . Для поддержки прошивки RAM-дисков производителей в загрузчике необходимо реализовать эти две команды.

Изменения Fastbootd

getvar:max-fetch-size аналогичен max-download-size . Он определяет максимальный размер данных, которые устройство может отправить в одном ответе DATA. Драйвер не должен получать данные размером больше этого значения.

fetch:name[:offset[:size]] выполняет серию проверок на устройстве. Если выполняются все следующие условия, команда fetch:name[:offset[:size]] возвращает данные:

  • Устройство работает под отладочной сборкой.
  • Устройство разблокировано (состояние загрузки оранжевое).
  • Извлеченное имя раздела — vendor_boot .
  • Значение size находится в диапазоне 0 < size <= max-fetch-size .

После проверки этих данных fetch:name[:offset[:size]] возвращает размер и смещение раздела. Обратите внимание на следующее:

  • fetch:name эквивалентно fetch:name:0 , что эквивалентно fetch:name:0:partition_size .
  • fetch:name:offset эквивалентно fetch:name:offset:(partition_size - offset)

Поэтому fetch:name[:offset[:size]] = fetch:name:offset:(partition_size - offset) .

Если offset или partition_size (или оба) не указаны, используются значения по умолчанию, где offset равен 0, а size — вычисленному значению partition_size - offset .

  • Смещение указано, размер не указан: size = partition_size - offset
  • Не указано ни одного: для обоих вариантов используются значения по умолчанию, size = partition_size - 0.

Например, fetch:foo извлекает весь раздел foo со смещением 0.

Изменения в драйверах

В инструмент fastboot добавлены команды для внесения изменений в драйверы. Полное описание каждой команды можно найти в таблице команд Fastboot .

  • fastboot fetch vendor_boot out.img

    • Вызывает getvar max-fetch-size для определения размера фрагмента.
    • Вызывает getvar partition-size:vendor_boot[_a] для определения размера всего раздела.
    • Вызывает fastboot fetch vendor_boot[_a]:offset:size для каждого фрагмента. (Размер фрагмента больше размера vendor_boot , поэтому обычно имеется только один фрагмент.)
    • Сшивает данные вместе в out.img .
  • fastboot flash vendor_boot:default vendor-ramdisk.img

    Это особый вариант команды flash. Он загружает образ vendor_boot , как если бы была вызвана fastboot fetch .

    • Если загрузчик поставщика имеет версию заголовка 3 , он выполняет следующие действия:
      • Заменяет ramdisk поставщика указанным образом.
      • Запускает новый образ vendor_boot .
    • Если загрузочный заголовок поставщика имеет версию 4 , он выполняет следующие действия:
      • Заменяет весь ramdisk поставщика указанным образом, так что указанный образ становится единственным фрагментом ramdisk поставщика в образе vendor_boot .
      • Пересчитывает размер и смещение в таблице ramdisk поставщика.
      • Запускает новый образ vendor_boot .
  • fastboot flash vendor_boot:foo vendor-ramdisk.img

    Извлекает vendor_boot image , как если бы была вызвана fastboot fetch .

    • Если загрузочный заголовок поставщика имеет версию 3, возвращается ошибка.
    • Если загрузочный заголовок поставщика имеет версию 4, он выполняет следующие действия:

      • Находит фрагмент ramdisk поставщика с именем ramdisk_<var>&lt;foo></var> . Если фрагмент не найден или найдено несколько совпадений, возвращает ошибку.
      • Заменяет фрагмент ramdisk поставщика указанным образом.
      • Пересчитывает каждый размер и смещение в таблице ramdisk поставщика.
      • Запускает новый образ vendor_boot .
    • Если <foo> не указан, он пытается найти ramdisk_ .

mkbootimg

Имя default зарезервировано для именования фрагментов RAM-диска поставщика в Android 12 и более поздних версиях. Хотя семантика fastboot flash vendor_boot:default остаётся прежней, вы не должны называть свои фрагменты RAM-диска как default .

Изменения SELinux

В fastbootd.te внесены изменения для поддержки перепрошивки RAM-дисков поставщиков.