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

В 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 напрямую).

Значение конфигурации системы как root различается в Android 9 и Android 10. В конфигурации системы как 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 см. в разделе Обновления системы 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 . Если между файлами наложений поставщика и файлами, которые они заменяют, существуют несоответствия контекста файла, укажите это в политике безопасности для конкретного устройства. Контекст файла задается на уровне каталога. Если контекст файла каталога наложения поставщика не соответствует целевому каталогу, а правильный контекст файла не указан в сеполитике для конкретного устройства, этот каталог наложения поставщика не накладывается на целевой каталог.

Чтобы использовать наложение поставщика, ядро ​​должно включить 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 и т. д.

Настройка дм-верити

В системе от имени 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"

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

При использовании системы от имени 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/* автоматически).