OEM-производители и поставщики SoC, которые хотят внедрить обновления системы A/B, должны убедиться, что их загрузчик реализует HAL boot_control и передает правильные параметры ядру.
Реализация управления загрузкой HAL
Загрузчики с поддержкой A/B должны реализовать HAL boot_control
в hardware/libhardware/include/hardware/boot_control.h
. Вы можете протестировать реализации с помощью утилиты system/extras/bootctl
и system/extras/tests/bootloader/
.
Вы также должны реализовать конечный автомат, показанный ниже:
![](https://source.android.google.cn/static/devices/tech/ota/images/ab-updates-state-machine.png?authuser=8&hl=ru)
Настройка ядра
Чтобы внедрить обновления системы A/B:
- Cherrypick выберете следующую серию патчей ядра (при необходимости):
- Если вы загружаетесь без виртуального диска и используете «загрузку как восстановление», Cherrypick android-review.googlesource.com/#/c/158491/ .
- Чтобы настроить dm-verity без виртуального диска, перейдите по ссылке android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- Убедитесь, что аргументы командной строки ядра содержат следующие дополнительные аргументы:
skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
<public-key-id>
— это идентификатор открытого ключа, используемого для проверки подписи таблицы истинности (подробности см. в разделе dm-verity ) . - Добавьте сертификат .X509, содержащий открытый ключ, в связку системных ключей:
- Скопируйте сертификат .X509, отформатированный в формате
.der
, в корень каталогаkernel
. Если сертификат .X509 отформатирован как файл.pem
, используйте следующую командуopenssl
для преобразования из.pem
в формат.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- Создайте
zImage
, чтобы включить сертификат как часть системного набора ключей. Для проверки проверьте записьprocfs
(требуетсяKEYS_CONFIG_DEBUG_PROC_KEYS
):angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
Успешное включение сертификата .X509 указывает на наличие открытого ключа в связке системных ключей (выделение обозначает идентификатор открытого ключа). - Замените пробел на
#
и передайте его как<public-key-id>
в командной строке ядра. Например,Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f
вместо<public-key-id>
.
- Скопируйте сертификат .X509, отформатированный в формате
Установка переменных сборки
Загрузчики с поддержкой A/B должны соответствовать следующим критериям переменных сборки:
Необходимо определить для цели A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Вы можете дополнительно выполнить шаг dex2oat после установки (но до перезагрузки), описанный в разделе Компиляция . |
---|---|
Настоятельно рекомендуется для цели A/B |
|
Невозможно определить цель A/B |
|
Необязательно для отладочных сборок | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Установка разделов (слотов)
Устройствам A/B не нужен раздел восстановления или раздел кэша, поскольку Android больше не использует эти разделы. Раздел данных теперь используется для загруженного пакета OTA, а код образа восстановления находится в загрузочном разделе. Все разделы с A/B-ed должны быть названы следующим образом (слоты всегда называются a
, b
и т. д.): boot_a
, boot_b
, system_a
, system_b
, vendor_a
, vendor_b
.
Кэш
Для обновлений, отличных от A/B, раздел кеша использовался для хранения загруженных пакетов OTA и для временного хранения блоков при применении обновлений. Никогда не было хорошего способа определить размер раздела кеша: его размер зависел от того, какие обновления вы хотели применить. В худшем случае размер раздела кеша равен размеру образа системы. С обновлениями A/B нет необходимости складывать блоки (поскольку вы всегда пишете в раздел, который в данный момент не используется), а с потоковым A/B нет необходимости загружать весь пакет OTA перед его применением.
Восстановление
RAM-диск восстановления теперь содержится в файле boot.img
. При входе в рекавери загрузчик не может указать параметр skip_initramfs
в командной строке ядра.
Для обновлений, отличных от A/B, раздел восстановления содержит код, используемый для применения обновлений. Обновления A/B применяются с помощью update_engine
, работающего в обычном загруженном образе системы. По-прежнему существует режим восстановления, используемый для реализации сброса заводских данных и загрузки неопубликованных пакетов обновлений (отсюда и произошло название «восстановление»). Код и данные для режима восстановления хранятся в обычном загрузочном разделе на виртуальном диске; чтобы загрузиться в образ системы, загрузчик говорит ядру пропустить виртуальный диск (иначе устройство загружается в режим восстановления. Режим восстановления небольшой (и большая его часть уже была на загрузочном разделе), поэтому загрузочный раздел не увеличивается по размеру.
Фстаб
Аргумент slotselect
должен быть в строке для разделов A/B. Например:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Ни один раздел не должен называться vendor
. Вместо этого раздел vendor_a
или vendor_b
будет выбран и смонтирован в точке монтирования /vendor
.
Аргументы слота ядра
Текущий суффикс слота должен быть передан либо через определенный узел дерева устройств (DT) ( /firmware/android/slot_suffix
), либо через командную строку ядра androidboot.slot_suffix
или аргумент bootconfig.
По умолчанию fastboot прошивает текущий слот на устройстве A/B. Если пакет обновления также содержит образы для другого, не текущего слота, fastboot также прошивает эти образы. Доступные варианты включают в себя:
-
--slot SLOT
. Переопределите поведение по умолчанию и предложите fastboot прошить слот, который передается в качестве аргумента. -
--set-active [ SLOT ]
. Установите слот как активный. Если необязательный аргумент не указан, то текущий слот устанавливается как активный. -
fastboot --help
. Получить подробную информацию о командах.
Если загрузчик реализует быструю загрузку, он должен поддерживать команду set_active <slot>
, которая устанавливает текущий активный слот в заданный слот (это также должно сбросить флаг незагружаемости для этого слота и сбросить счетчик повторных попыток до значений по умолчанию). Загрузчик также должен поддерживать следующие переменные:
-
has-slot:<partition-base-name-without-suffix>
. Возвращает «да», если данный раздел поддерживает слоты, иначе «нет». -
current-slot
. Возвращает суффикс слота, из которого будет загружаться следующий. -
slot-count
. Возвращает целое число, представляющее количество доступных слотов. В настоящее время поддерживаются два слота, поэтому это значение равно2
. -
slot-successful:<slot-suffix>
. Возвращает «да», если данный слот помечен как успешно загружающийся, и «нет» в противном случае. -
slot-unbootable:<slot-suffix>
. Возвращает «да», если данный слот помечен как незагружаемый, «нет» в противном случае. -
slot-retry-count
. Количество попыток, оставшихся для загрузки данного слота.
Чтобы просмотреть все переменные, запустите fastboot getvar all
.
Генерация пакетов OTA
Инструменты пакета OTA следуют тем же командам, что и команды для устройств, отличных от A/B. Файл target_files.zip
должен быть сгенерирован путем определения переменных сборки для цели A/B. Инструменты пакетов OTA автоматически идентифицируют и создают пакеты в формате для средства обновления A/B.
Примеры:
- Для создания полного OTA:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- Для создания инкрементного OTA:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Настройка разделов
update_engine
может обновлять любую пару разделов A/B, определенных на одном диске. Пара разделов имеет общий префикс (например, system
или boot
) и суффикс для каждого слота (например, _a
). Список разделов, для которых генератор полезной нагрузки определяет обновление, настраивается с помощью переменной make AB_OTA_PARTITIONS
.
Например, если включена пара разделов bootloader_a
и bootloader_b ( _a
и booloader_b
— _b
слотов), вы можете обновить эти разделы, указав следующее в конфигурации продукта или платы:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Все разделы, обновленные с помощью update_engine
, не должны изменяться остальной частью системы. Во время добавочных или дельта -обновлений двоичные данные из текущего слота используются для создания данных в новом слоте. Любое изменение может привести к сбою проверки новых данных слота в процессе обновления и, следовательно, к сбою обновления.
Настройка после установки
Вы можете настроить этап после установки по-разному для каждого обновленного раздела, используя набор пар ключ-значение. Чтобы запустить программу, расположенную в /system/usr/bin/postinst
в новом образе, укажите путь относительно корня файловой системы в системном разделе.
Например, usr/bin/postinst
— это system/usr/bin/postinst
(если не используется RAM-диск). Кроме того, укажите тип файловой системы для передачи системному вызову mount(2)
. Добавьте следующее в файлы продукта или устройства .mk
(если применимо):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Компиляция
По соображениям безопасности system_server
не может использовать JIT- компиляцию. Это означает, что вы должны заранее скомпилировать файлы odex для system_server
и его зависимостей как минимум; все остальное необязательно.
Для компиляции приложений в фоновом режиме необходимо добавить следующее в конфигурацию устройства продукта (в файле device.mk продукта):
- Включите собственные компоненты в сборку, чтобы убедиться, что сценарий компиляции и двоичные файлы скомпилированы и включены в образ системы.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- Подключите скрипт компиляции к
update_engine
, чтобы он выполнялся после установки.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
Справку по установке предварительно выбранных файлов в неиспользуемом втором системном разделе см. в разделе Установка файлов DEX_PREOPT при первой загрузке .