Diseño de partición

En Android 10, el sistema de archivos raíz ya no se incluye en ramdisk.img y, en cambio, se fusiona con system.img (es decir, system.img siempre se crea como si se hubiera configurado BOARD_BUILD_SYSTEM_ROOT_IMAGE ). Dispositivos que se inician con Android 10:

  • Use un diseño de partición del sistema como raíz (aplicado automáticamente por la compilación sin opciones para cambiar el comportamiento).
  • Debe usar un ramdisk, que es necesario para dm-linear.
  • Debe establecer BOARD_BUILD_SYSTEM_ROOT_IMAGE en false . Esta configuración se usa solo para diferenciar entre dispositivos que usan un ramdisk y dispositivos que no usan un ramdisk (y en su lugar montan system.img directamente).

El significado de una configuración de sistema como raíz difiere entre Android 9 y Android 10. En una configuración de sistema como raíz de Android 9, BOARD_BUILD_SYSTEM_ROOT_IMAGE se establece en true , lo que obliga a la compilación a fusionar el sistema de archivos raíz en system.img y luego monte system.img como el sistema de archivos raíz (rootfs). Esta configuración es obligatoria para los dispositivos que se inician con Android 9, pero es opcional para los dispositivos que se actualizan a Android 9 y para los dispositivos que ejecutan versiones anteriores de Android. En una configuración de sistema como raíz de Android 10, la compilación siempre fusiona $TARGET_SYSTEM_OUT y $TARGET_ROOT_OUT en system.img ; esta configuración es el comportamiento predeterminado para todos los dispositivos que ejecutan Android 10.

Android 10 realiza cambios adicionales para admitir particiones dinámicas , un sistema de partición del espacio de usuario que permite actualizaciones inalámbricas (OTA) para crear, cambiar el tamaño o destruir particiones. Como parte de este cambio, el kernel de Linux ya no puede montar la partición del sistema lógico en dispositivos que ejecutan Android 10, por lo que esta operación la maneja la primera etapa init.

Las siguientes secciones describen los requisitos del sistema como raíz para las OTA solo del sistema, brindan orientación sobre la actualización de dispositivos para usar el sistema como raíz (incluidos los cambios en el diseño de la partición y los requisitos del kernel dm-verity). Para obtener detalles sobre los cambios en ramdisk, consulte Particiones de ramdisk .

Acerca de las OTA solo del sistema

Las OTA solo del sistema, que permiten que las versiones de Android actualicen system.img y product.img sin cambiar otras particiones, requieren un diseño de partición del sistema como raíz. Todos los dispositivos que ejecutan Android 10 deben usar un diseño de partición de sistema como raíz para habilitar las OTA solo del sistema.

Para obtener detalles sobre los dispositivos A/B y no A/B, consulte Actualizaciones del sistema A/B (continuas) .

Uso de superposición de proveedores

La superposición de proveedores le permite superponer cambios en la partición del vendor en el momento del arranque del dispositivo. Una superposición de proveedor es un conjunto de módulos de proveedor en la partición del product que se superponen en la partición del vendor cuando se inicia el dispositivo, reemplazando y agregando módulos existentes.

Cuando el dispositivo arranca, el proceso de init completa el montaje de la primera etapa y lee las propiedades predeterminadas. Luego busca /product/vendor_overlay/<target_vendor_version> y monta cada subdirectorio en su directorio de partición de vendor correspondiente, si se cumplen las siguientes condiciones:

  • /vendor/<overlay_dir> existe.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> tiene el mismo contexto de archivo que /vendor/<overlay_dir> .
  • init puede montarse en el contexto de archivo de /vendor/<overlay_dir> .

Implementación de superposición de proveedores

Instale archivos de superposición de proveedores en /product/vendor_overlay/<target_vendor_version> . Esos archivos se superponen a la partición del vendor cuando se inicia el dispositivo, reemplazando los archivos del mismo nombre y agregando cualquier archivo nuevo. La superposición del proveedor no puede eliminar archivos de la partición del vendor .

Los archivos de superposición del proveedor deben tener el mismo contexto de archivo que los archivos de destino que reemplazan en la partición del vendor . De forma predeterminada, los archivos en el /product/vendor_overlay/<target_vendor_version> tienen el contexto de vendor_file . Si hay discrepancias en el contexto del archivo entre los archivos superpuestos del proveedor y los archivos que reemplazan, especifíquelo en la política específica del dispositivo. El contexto del archivo se establece en el nivel del directorio. Si el contexto de archivo de un directorio de superposición de proveedor no coincide con el directorio de destino y el contexto de archivo correcto no se especifica en la política específica del dispositivo, ese directorio de superposición de proveedor no se superpone en el directorio de destino.

Para usar la superposición del proveedor, el kernel debe habilitar OverlayFS configurando CONFIG_OVERLAY_FS=y . Además, el kernel debe fusionarse desde el kernel común 4.4 o posterior, o parchearse con "overlayfs: override_creds=off option bypass creator_cred" .

Ejemplo de implementación de superposición de proveedores

Este procedimiento demuestra la implementación de una superposición de proveedores que superpone los directorios /vendor/lib/* , /vendor/etc/* y /vendor/app/* .

  1. Agregue archivos de proveedores preconstruidos en 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. Instale los archivos de proveedores preconstruidos en product/vendor_overlay en 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. Defina contextos de archivo si los archivos de partición de vendor de destino tienen contextos distintos de vendor_file . Debido a que /vendor/lib/* usa el contexto de vendor_file , este ejemplo no incluye ese directorio.

    Agrega lo siguiente a 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. Permita que el proceso de init monte la superposición del proveedor en contextos de archivo que no sean vendor_file . Debido a que el proceso de init ya tiene permiso para montarse en el contexto de vendor_file , este ejemplo no define la política para vendor_file .

    Agrega lo siguiente a device/google/device-sepolicy/public/init.te :

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

Validación de superposición de proveedores

Para validar la configuración de superposición del proveedor, agregue archivos en /product/vendor_overlay/<target_vendor_version>/<overlay_dir> y verifique si los archivos están superpuestos en los archivos en /vendor/<overlay_dir> .

Para compilaciones de userdebug de usuarios, hay un módulo de prueba para Atest :

$ atest -v fs_mgr_vendor_overlay_test

Actualización al sistema como root

Para actualizar dispositivos que no sean A/B para usar system-as-root, debe actualizar el esquema de partición para boot.img y system.img , configurar dm-verity y eliminar cualquier dependencia de arranque en las carpetas raíz específicas del dispositivo.

Actualización de particiones

A diferencia de los dispositivos A/B que reutilizan /boot como partición de recuperación , los dispositivos que no son A/B deben mantener la partición /recovery separada, ya que no tienen la partición de ranura de reserva (por ejemplo, de boot_a a boot_b ). Si /recovery se elimina en un dispositivo que no es A/B y se hace similar al esquema A/B, el modo de recuperación podría interrumpirse durante una actualización fallida de la partición /boot . Por esta razón, la partición /recovery debe ser una partición separada de /boot para dispositivos que no sean A/B, lo que implica que la imagen de recuperación continuará actualizándose de manera diferida (es decir, igual que en los dispositivos que ejecutan Android). 8.1.0 o inferior).

La siguiente tabla enumera las diferencias de partición de imágenes para dispositivos que no son A/B antes y después de Android 9.

Imagen Ramdisk (antes de 9) Sistema como raíz (después de 9)
boot.img Contiene un kernel y un ramdisk.img :
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
Contiene solo un kernel de arranque normal.
recovery.img Contiene un kernel de recuperación y un ramdisk.img de recuperación.
system.img Contiene lo siguiente:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
Contiene el contenido combinado de system.img y ramdisk.img originales:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

Las particiones en sí no cambian; tanto ramdisk como system-as-root utilizan el siguiente esquema de partición:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor , etc

Configuración de dm-verity

En system-as-root, el kernel debe montar system.img bajo / (punto de montaje) con dm-verity . AOSP es compatible con las siguientes implementaciones de dm-verity para system.img .

vboot 1.0

Para vboot 1.0 , el kernel debe analizar los metadatos específicos de Android en /system y luego convertirlos a parámetros dm-verity para configurar dm-verity (requiere estos parches del kernel ). El siguiente ejemplo muestra la configuración relacionada con dm-verity para system-as-root en la línea de comando del kernel:

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

Para vboot 2.0 ( AVB ), el cargador de arranque debe integrar external/avb/libavb , que luego analiza el descriptor hashtree para /system , lo convierte en parámetros dm-verity y finalmente pasa los parámetros al kernel a través de la línea de comando del kernel. (Los descriptores de hashtree de /system pueden estar en /vbmeta o en /system mismo).

vboot 2.0 requiere los siguientes parches del kernel:

El siguiente ejemplo muestra la configuración relacionada con dm-verity para system-as-root en la línea de comando del kernel:

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"

Uso de carpetas raíz específicas del dispositivo

Con el sistema como raíz, después de que la imagen genérica del sistema (GSI) se muestre en el dispositivo (y antes de ejecutar las pruebas de Vendor Test Suite ), todas las carpetas raíz específicas del dispositivo agregadas con BOARD_ROOT_EXTRA_FOLDERS desaparecen porque todo el contenido del directorio raíz ha sido reemplazado por el sistema como raíz GSI. La eliminación de estas carpetas puede hacer que el dispositivo no se pueda iniciar si existe una dependencia de las carpetas raíz específicas del dispositivo (por ejemplo, se usan como puntos de montaje).

Para evitar este problema, no utilice BOARD_ROOT_EXTRA_FOLDERS para agregar carpetas raíz específicas del dispositivo. Si necesita especificar puntos de montaje específicos del dispositivo, use /mnt/vendor/<mount point> (agregado en estas listas de cambios). Estos puntos de montaje específicos del proveedor se pueden especificar directamente tanto en el árbol de dispositivos fstab (para el montaje de primera etapa) como en el archivo /vendor/etc/fstab.{ro.hardware} sin configuración adicional (ya que fs_mgr los crea en /mnt/vendor/* automáticamente).