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

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

Объединение fastboot и recovery

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

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

Команды ADB

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

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

Команды Fastboot

В этом разделе описаны команды 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 и более поздних версиях для поддержки прошивки виртуальных дисков поставщика.

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

Подробнее о том, как настроить параметры конфиденциальностиfastboot fetch vendor_boot <out.img>…

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

Используется в Android 12 и более поздних версий для поддержки прошивки ramdisk поставщика.

Это специальный вариант команды 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. Возвращает ошибку, если заголовок загрузчика поставщика имеет версию 3. Если это версия 4, она находит правильный фрагмент ramdisk поставщика (если он доступен). Заменяет его на указанное изображение, пересчитывает размеры и смещения и обновляет новый 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 Перезагрузка в режиме fastboot.
reboot recovery Перезагрузка в режим восстановления.
getvar Получает переменную загрузчика операционной системы, которая требуется для прошивки образа восстановления или загрузочного образа (например, current-slot и max-download-size).
oem <command> Команда, заданная производителем оригинального оборудования.

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

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

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

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

Fastboot OEM HAL

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

Определение HAL для Fastboot:

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. Убедитесь, что HAL fastboot, HAL управления загрузкой и HAL состояния упакованы как часть образа восстановления.

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

Чтобы проверить fastboot в пространстве пользователя, запустите Vendor Test Suite (VTS).

Образы дисков поставщика флеш-памяти

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

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

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

Команды getvar:max-fetch-size и fetch:name реализованы в fastbootd. Чтобы загрузчик поддерживал прошивку ramdisk поставщика, необходимо реализовать следующие две команды:

Изменения в 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), используются значения по умолчанию: 0 для offset и вычисленное значение partition_size - offset для size.

  • Указан сдвиг, но не указан размер: 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.

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

mkbootimg

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

Изменения SELinux

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