Diseño de particiones

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

  • Usar un diseño de partición de system-as-root (se aplica automáticamente con la compilación sin opciones para cambiar el comportamiento)
  • Debe usar un disco RAM, que es obligatorio para dm-linear.
  • Se debe establecer BOARD_BUILD_SYSTEM_ROOT_IMAGE en false. Este parámetro de configuración solo se usa para diferenciar entre los dispositivos que usan un ramdisk y los que no lo usan (y, en cambio, 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 combinar el sistema de archivos raíz en system.img y, luego, a montar system.img como el sistema de archivos raíz (rootfs). Esta configuración es obligatoria para los dispositivos que se lanzan 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 combina $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 más cambios para admitir particiones dinámicas, un sistema de particiones de espacio de usuario que permite que las actualizaciones inalámbricas (OTA) creen, redimensionen o destruyan particiones. Como parte de este cambio, el kernel de Linux ya no puede activar la partición lógica del sistema en dispositivos que ejecutan Android 10, por lo que esta operación la controla el init de primera etapa.

En las siguientes secciones, se describen los requisitos de sistema como raíz para las actualizaciones inalámbricas solo del sistema y se brinda orientación para actualizar los dispositivos para que usen el sistema como raíz (incluidos los cambios en el diseño de la partición y los requisitos del kernel de dm-verity). Para obtener detalles sobre los cambios en el ramdisk, consulta 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 de system-as-root. 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.

  • Los dispositivos A/B, que activan la partición system como rootfs, ya usan system-as-root y no requieren cambios para admitir las OTA del sistema.
  • Los dispositivos que no son A/B, que montan la partición system en /system, se deben actualizar para usar un diseño de partición system-as-root para admitir las OTA del sistema.

Para obtener detalles sobre los dispositivos A/B y los que no son A/B, consulta Actualizaciones de sistema A/B (sin interrupciones).

Usa la superposición del proveedor (<= AOSP 14)

La superposición del proveedor te permite superponer cambios en la partición vendor en el momento del inicio del dispositivo. Una superposición del proveedor es un conjunto de módulos del proveedor en la partición product que se superponen en la partición vendor cuando se inicia el dispositivo, lo que reemplaza y agrega a los módulos existentes.

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

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

Implementa la superposición del proveedor

Instala archivos de superposición del proveedor en /product/vendor_overlay/<target_vendor_version>. Esos archivos se superponen en la partición vendor cuando se inicia el dispositivo, reemplazan los archivos del mismo nombre y agregan los archivos nuevos. La superposición del proveedor no puede quitar archivos de la partición 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 vendor. De forma predeterminada, los archivos del directorio /product/vendor_overlay/<target_vendor_version> tienen el contexto vendor_file. Si hay discrepancias en el contexto de los archivos entre los archivos de superposición del proveedor y los archivos que reemplazan, especifícalo en la política de seguridad específica del dispositivo. El contexto del archivo se establece a nivel del directorio. Si el contexto de archivo de un directorio de superposición del proveedor no coincide con el directorio de destino y no se especifica el contexto de archivo correcto en la sepolicy específica del dispositivo, ese directorio de superposición del 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 combinarse desde el kernel común 4.4 o posterior, o bien parchearse con "overlayfs: override_creds=off option bypass creator_cred".

Ejemplo de implementación de la superposición del proveedor

En este procedimiento, se muestra la implementación de una superposición del proveedor que superpone los directorios /vendor/lib/*, /vendor/etc/* y /vendor/app/*.

  1. Agrega archivos de proveedores prediseñados 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. Instala los archivos del proveedor prediseñados 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. Define contextos de archivo si los archivos de partición de vendor de destino tienen contextos distintos de vendor_file. Como /vendor/lib/* usa el contexto 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. Permite que el proceso init active la superposición del proveedor en contextos de archivos que no sean vendor_file. Como el proceso init ya tiene permiso para realizar el montaje en el contexto 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;

Valida la superposición del proveedor

Para validar la configuración de la superposición del proveedor, agrega archivos en /product/vendor_overlay/<target_vendor_version>/<overlay_dir> y verifica si se superponen en los archivos de /vendor/<overlay_dir>.

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

$ atest -v fs_mgr_vendor_overlay_test

Actualización a system-as-root

Para actualizar los dispositivos que no son A/B para que usen el sistema como raíz, debes actualizar el esquema de partición para boot.img y system.img, configurar dm-verity y quitar cualquier dependencia de arranque en las carpetas raíz específicas del dispositivo.

Actualiza particiones

A diferencia de los dispositivos A/B que reutilizan /boot como la 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 resguardo (por ejemplo, de boot_a a boot_b). Si se quita /recovery en un dispositivo que no es A/B y se hace similar al esquema A/B, el modo de recuperación podría fallar durante una actualización fallida a la partición /boot. Por este motivo, la partición /recovery debe ser una partición independiente de /boot para los dispositivos que no son A/B, lo que implica que la imagen de recuperación se sigue actualizando de forma diferida (es decir, igual que en los dispositivos que ejecutan Android 8.1.0 o versiones anteriores).

En la siguiente tabla, se enumeran las diferencias en las particiones de imágenes para dispositivos que no son A/B antes y después de Android 9.

Imagen Ramdisk (antes de Android 9) System-as-root (después de Android 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 usan el siguiente esquema de partición:

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

Cómo configurar dm-verity

En el sistema como raíz, el kernel debe activar system.img en / (punto de activación) con dm-verity. El AOSP admite las siguientes implementaciones de dm-verity para system.img.

vboot 1.0

En el caso de vboot 1.0, el kernel debe analizar los metadatos específicos de Android en /system y, luego, convertirlos en parámetros de dm-verity para configurar dm-verity (requiere estos parches del kernel). En el siguiente ejemplo, se muestran los parámetros de configuración relacionados con dm-verity para system-as-root en la línea de comandos 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 bootloader debe integrar external/avb/libavb, que luego analiza el descriptor de hashtree para /system, lo convierte en parámetros de dm-verity y, finalmente, pasa los parámetros al kernel a través de la línea de comandos del kernel. (Los descriptores de árbol hash de /system pueden estar en /vbmeta o en /system).

vboot 2.0 requiere los siguientes parches del kernel:

En el siguiente ejemplo, se muestran los parámetros de configuración relacionados con dm-verity para system-as-root en la línea de comandos 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"

Usa carpetas raíz específicas del dispositivo

Con system-as-root, después de que se escribe la imagen genérica del sistema (GSI) en el dispositivo (y antes de ejecutar las pruebas del conjunto de pruebas del proveedor), desaparecen todas las carpetas raíz específicas del dispositivo que se agregaron con BOARD_ROOT_EXTRA_FOLDERS, ya que todo el contenido del directorio raíz se reemplazó por la GSI de system-as-root. La eliminación de estas carpetas puede provocar que el dispositivo no se pueda iniciar si existe una dependencia de las carpetas raíz específicas del dispositivo (por ejemplo, si se usan como puntos de montaje).

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