Макет раздела

В Android 10 корневая файловая система больше не включается в ramdisk.img и вместо этого объединяется с system.img (то есть system.img всегда создается так, как если бы был установлен BOARD_BUILD_SYSTEM_ROOT_IMAGE ). Устройства, запускаемые с Android 10:

  • Используйте макет раздела «система от имени корня» (автоматически применяется сборкой без параметров для изменения поведения).
  • Должен использоваться виртуальный диск, необходимый для dm-linear.
  • Необходимо установить для BOARD_BUILD_SYSTEM_ROOT_IMAGE значение false . Этот параметр используется только для того, чтобы различать устройства, которые используют виртуальный диск, и устройства, которые не используют виртуальный диск (и вместо этого монтируют system.img напрямую).

Значение конфигурации system-as-root различается в Android 9 и Android 10. В конфигурации system-as-root Android 9 для параметра BOARD_BUILD_SYSTEM_ROOT_IMAGE установлено значение true , что заставляет сборку объединить корневую файловую систему с system.img , а затем смонтировать system.img как корневую файловую систему (rootfs). Эта конфигурация обязательна для устройств, запускаемых с Android 9, но необязательна для устройств, обновляющихся до Android 9, и для устройств с более ранними версиями Android. В конфигурации системы Android 10 как root сборка всегда объединяет $TARGET_SYSTEM_OUT и $TARGET_ROOT_OUT в system.img ; эта конфигурация является поведением по умолчанию для всех устройств под управлением Android 10.

В Android 10 внесены дополнительные изменения для поддержки динамических разделов — системы разделения пользовательского пространства, которая позволяет выполнять беспроводные (OTA) обновления для создания, изменения размера или уничтожения разделов. В рамках этого изменения ядро ​​Linux больше не может монтировать логический системный раздел на устройствах под управлением Android 10, поэтому эта операция выполняется на первом этапе инициализации.

В следующих разделах описываются требования системы от имени пользователя root для системных OTA, а также рекомендации по обновлению устройств для использования системы от имени пользователя root (включая изменения макета раздела и требования к ядру dm-verity). Подробнее об изменениях виртуального диска см. Разделы виртуального диска .

О системных OTA

OTA только для системы, которые позволяют выпускам Android обновлять system.img и product.img без изменения других разделов, требуют расположения системы как корневого раздела. Все устройства под управлением Android 10 должны использовать макет раздела «система как корневой», чтобы включить OTA только для системы.

Подробнее об устройствах A/B и других устройствах см. в разделе Обновления системы A/B (бесшовные) .

Использование наложения поставщика

Наложение поставщика позволяет накладывать изменения на раздел vendor во время загрузки устройства. Наложение поставщика — это набор модулей поставщика в разделе product , которые накладываются на раздел vendor при загрузке устройства, заменяя и добавляя существующие модули.

Когда устройство загружается, процесс init завершает монтирование первого этапа и считывает свойства по умолчанию. Затем он ищет /product/vendor_overlay/<target_vendor_version> и монтирует каждый подкаталог в соответствующем каталоге раздела vendor , если выполняются следующие условия:

  • /vendor/<overlay_dir> существует.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> имеет тот же файловый контекст, что и /vendor/<overlay_dir> .
  • init разрешено монтировать в контексте файла /vendor/<overlay_dir> .

Реализация наложения поставщиков

Установите файлы наложения поставщика в /product/vendor_overlay/<target_vendor_version> . Эти файлы перекрывают раздел vendor при загрузке устройства, заменяя файлы с тем же именем и добавляя новые файлы. Оверлей поставщика не может удалять файлы из раздела vendor .

Файлы наложения поставщика должны иметь тот же файловый контекст, что и целевые файлы, которые они заменяют в разделе vendor . По умолчанию файлы в каталоге /product/vendor_overlay/<target_vendor_version> имеют контекст vendor_file . Если существуют несоответствия файлового контекста между файлами наложения поставщика и файлами, которые они заменяют, укажите это в политике sepolicy для конкретного устройства. Контекст файла задается на уровне каталога. Если контекст файла в каталоге наложения поставщика не соответствует целевому каталогу, а правильный контекст файла не указан в политике sepolicy для конкретного устройства, этот каталог наложения поставщика не накладывается на целевой каталог.

Чтобы использовать наложение поставщика, ядро ​​должно включить OverlayFS, установив CONFIG_OVERLAY_FS=y . Также ядро ​​должно быть слито из общего ядра 4.4 или новее, либо пропатчено с помощью "overlayfs: override_creds=off option bypass creator_cred" .

Пример реализации наложения поставщика

Эта процедура демонстрирует реализацию наложения поставщика, которое перекрывает каталоги /vendor/lib/* , /vendor/etc/* и /vendor/app/* .

  1. Добавьте готовые файлы поставщиков в device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/ :

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
    
  2. Установите готовые файлы поставщиков в product/vendor_overlay в device/google/device/device.mk :

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
    
  3. Определите файловые контексты, если файлы разделов целевого vendor имеют контексты, отличные от vendor_file . Поскольку /vendor/lib/* использует контекст vendor_file , в этом примере этот каталог не используется.

    Добавьте следующее в device/google/device-sepolicy/private/file_contexts :

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
    
  4. Разрешить процессу init монтировать оверлей поставщика в контекстах файлов, отличных от vendor_file . Поскольку процесс init уже имеет разрешение на монтирование в контексте vendor_file , в этом примере политика для vendor_file не определяется.

    Добавьте следующее в device/google/device-sepolicy/public/init.te :

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;
    

Проверка наложения поставщика

Чтобы проверить конфигурацию наложения поставщика, добавьте файлы в /product/vendor_overlay/<target_vendor_version>/<overlay_dir> и проверьте, накладываются ли файлы на файлы в /vendor/<overlay_dir> .

Для сборок userdebug есть тестовый модуль для Atest :

$ atest -v fs_mgr_vendor_overlay_test

Обновление до системы от имени root

Чтобы обновить устройства, отличные от A/B, для использования системы от имени root, вы должны обновить схему разбиения на разделы для boot.img и system.img , настроить dm-verity и удалить все зависимости загрузки от корневых папок конкретного устройства.

Обновление разделов

В отличие от устройств A/B, которые переназначают /boot в качестве раздела восстановления , устройства, отличные от A/B, должны хранить раздел /recovery отдельно, поскольку у них нет раздела резервного слота (например, из boot_a в boot_b ). Если /recovery удалить на устройстве, отличном от A/B, и сделать его похожим на схему A/B, режим восстановления может прерваться во время неудачного обновления раздела /boot . По этой причине раздел /recovery должен быть отдельным разделом от /boot для устройств, отличных от A/B, что означает, что образ восстановления будет по-прежнему обновляться отложенным образом (то есть так же, как на устройствах под управлением Android). 8.1.0 или ниже).

В следующей таблице перечислены различия в разделах образа для устройств, отличных от A/B, до и после Android 9.

Изображение Рамдиск (до 9) Система от имени root (после 9)
boot.img Содержит ядро ​​и ramdisk.img :
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
Содержит только обычное загрузочное ядро.
recovery.img Содержит ядро ​​восстановления и файл восстановления ramdisk.img .
system.img Содержит следующее:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Содержит объединенное содержимое исходного system.img и ramdisk.img :
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

Сами разделы не меняются; и виртуальный диск, и система от имени пользователя root используют следующую схему разделов:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor и т.д.

Настройка dm-verity

В системе от имени root ядро ​​должно монтировать system.img в / (точка монтирования) с помощью dm-verity . AOSP поддерживает следующие реализации dm-verity для system.img .

vboot 1.0

Для vboot 1.0 ядро ​​должно проанализировать специфичные для Android метаданные в /system , а затем преобразовать в параметры dm-verity для настройки dm-verity (требуются эти исправления ядра ). В следующем примере показаны настройки, связанные с dm-verity, для системы от имени пользователя root в командной строке ядра:

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

Для vboot 2.0 ( AVB ) загрузчик должен интегрировать external/avb/libavb , который затем анализирует дескриптор хеш -дерева для /system , преобразует его в параметры dm-verity и, наконец, передает параметры ядру через командную строку ядра. (Хэш-дескрипторы /system могут находиться в /vbmeta или в самой /system .)

vboot 2.0 требует следующих исправлений ядра:

В следующем примере показаны настройки, связанные с dm-verity, для системы от имени пользователя root в командной строке ядра:

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

Использование корневых папок для конкретных устройств

При использовании system-as-root после того, как общий образ системы (GSI) прошивается на устройстве (и перед запуском тестов Vendor Test Suite ), любые корневые папки для конкретного устройства, добавленные с помощью BOARD_ROOT_EXTRA_FOLDERS , исчезают, поскольку все содержимое корневого каталога было заменено. GSI системы от имени root. Удаление этих папок может привести к тому, что устройство перестанет загружаться, если существует зависимость от корневых папок устройства (например, они используются в качестве точек подключения).

Чтобы избежать этой проблемы, не используйте BOARD_ROOT_EXTRA_FOLDERS для добавления корневых папок для конкретных устройств. Если вам нужно указать точки монтирования для конкретного устройства, используйте /mnt/vendor/<mount point> (добавлено в эти списки изменений ). Эти точки монтирования, зависящие от поставщика, могут быть указаны напрямую как в дереве устройств fstab (для монтирования на первом этапе), так и в файле /vendor/etc/fstab.{ro.hardware} без дополнительной настройки (поскольку fs_mgr создает их в /mnt/vendor/* автоматически).