Los fabricantes de OEM y proveedores de SoC que deseen implementar actualizaciones del sistema A/B deben asegurarse de que su gestor de arranque implemente boot_control HAL y pase los parámetros correctos al kernel.
Implementar el control de arranque HAL
Los cargadores de arranque con capacidad A/B deben implementar boot_control
HAL en hardware/libhardware/include/hardware/boot_control.h
. Puede probar implementaciones utilizando la utilidad system/extras/bootctl
y system/extras/tests/bootloader/
.
También debes implementar la máquina de estados que se muestra a continuación:
Configurar el kernel
Para implementar actualizaciones del sistema A/B:
- Seleccione la siguiente serie de parches del kernel (si es necesario):
- Si arranca sin disco RAM y usa "arrancar como recuperación", seleccione android-review.googlesource.com/#/c/158491/ .
- Para configurar dm-verity sin ramdisk, seleccione android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- Asegúrese de que los argumentos de la línea de comando del kernel contengan los siguientes argumentos adicionales:
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>
es el ID de la clave pública utilizada para verificar la firma de la tabla de verdad (para obtener más detalles, consulte dm-verity ). . - Agregue el certificado .X509 que contiene la clave pública al conjunto de claves del sistema:
- Copie el certificado .X509 formateado en formato
.der
a la raíz del directoriokernel
. Si el certificado .X509 está formateado como un archivo.pem
, use el siguiente comandoopenssl
para convertir del formato.pem
al formato.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- Cree
zImage
para incluir el certificado como parte del conjunto de claves del sistema. Para verificar, verifique la entradaprocfs
(requiere queKEYS_CONFIG_DEBUG_PROC_KEYS
esté habilitado):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
La inclusión exitosa del certificado .X509 indica la presencia de la clave pública en el conjunto de claves del sistema (resaltado indica el ID de la clave pública). - Reemplace el espacio con
#
y páselo como<public-key-id>
en la línea de comando del kernel. Por ejemplo, paseAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
en lugar de<public-key-id>
.
- Copie el certificado .X509 formateado en formato
Establecer variables de compilación
Los cargadores de arranque con capacidad A/B deben cumplir los siguientes criterios de variables de compilación:
Debe definirse para el objetivo A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Opcionalmente, puede realizar el paso dex2oat posterior a la instalación (pero previo al reinicio) que se describe en Compilación . |
---|---|
Altamente recomendado para el objetivo A/B |
|
No se puede definir para el objetivo A/B |
|
Opcional para compilaciones de depuración | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Establecer particiones (ranuras)
Los dispositivos A/B no necesitan una partición de recuperación o una partición de caché porque Android ya no usa estas particiones. La partición de datos ahora se usa para el paquete OTA descargado y el código de la imagen de recuperación está en la partición de inicio. Todas las particiones A/B deben denominarse de la siguiente manera (las ranuras siempre se denominan a
, b
, etc.): boot_a
, boot_b
, system_a
, system_b
, vendor_a
, vendor_b
.
Cache
Para las actualizaciones que no son A/B, la partición de caché se usó para almacenar paquetes OTA descargados y para ocultar bloques temporalmente mientras se aplican las actualizaciones. Nunca hubo una buena manera de dimensionar la partición de caché: su tamaño dependía de las actualizaciones que deseaba aplicar. El peor de los casos sería una partición de caché tan grande como la imagen del sistema. Con las actualizaciones A/B no hay necesidad de guardar bloques (porque siempre estás escribiendo en una partición que no se usa actualmente) y con la transmisión A/B no hay necesidad de descargar el paquete OTA completo antes de aplicarlo.
Recuperación
El disco RAM de recuperación ahora está contenido en el archivo boot.img
. Al entrar en recuperación, el gestor de arranque no puede colocar la opción skip_initramfs
en la línea de comando del kernel.
Para actualizaciones que no son A/B, la partición de recuperación contiene el código utilizado para aplicar las actualizaciones. Las actualizaciones A/B se aplican mediante update_engine
que se ejecuta en la imagen del sistema de inicio normal. Todavía hay un modo de recuperación que se utiliza para implementar el restablecimiento de datos de fábrica y la descarga de paquetes de actualización (de donde proviene el nombre "recuperación"). El código y los datos para el modo de recuperación se almacenan en la partición de inicio normal en un disco RAM; para arrancar en la imagen del sistema, el gestor de arranque le dice al kernel que omita el disco RAM (de lo contrario, el dispositivo arranca en modo de recuperación. El modo de recuperación es pequeño (y gran parte ya estaba en la partición de arranque), por lo que la partición de arranque no aumenta en tamaño.
Fstab
El argumento slotselect
debe estar en la línea para las particiones editadas en A/B. Por ejemplo:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Ninguna partición debe denominarse vendor
. En su lugar, se seleccionará la partición vendor_a
o vendor_b
y se montará en el punto de montaje /vendor
.
Argumentos de la ranura del kernel
El sufijo de ranura actual debe pasarse a través de un nodo del árbol de dispositivos (DT) específico ( /firmware/android/slot_suffix
) o a través de la línea de comando del kernel androidboot.slot_suffix
o el argumento bootconfig.
De forma predeterminada, fastboot muestra la ranura actual en un dispositivo A/B. Si el paquete de actualización también contiene imágenes para la otra ranura no actual, fastboot también muestra esas imágenes. Las opciones disponibles incluyen:
-
--slot SLOT
. Anule el comportamiento predeterminado y solicite a fastboot que actualice la ranura que se pasa como argumento. -
--set-active [ SLOT ]
. Establece la ranura como activa. Si no se especifica ningún argumento opcional, entonces la ranura actual se establece como activa. -
fastboot --help
. Obtenga detalles sobre los comandos.
Si el gestor de arranque implementa fastboot, debería admitir el comando set_active <slot>
que establece la ranura activa actual en la ranura dada (esto también debe borrar el indicador de no arranque para esa ranura y restablecer el recuento de reintentos a los valores predeterminados). El gestor de arranque también debería admitir las siguientes variables:
-
has-slot:<partition-base-name-without-suffix>
. Devuelve "sí" si la partición dada admite ranuras, "no" en caso contrario. -
current-slot
. Devuelve el sufijo de la ranura que se iniciará a continuación. -
slot-count
. Devuelve un número entero que representa el número de espacios disponibles. Actualmente, se admiten dos ranuras, por lo que este valor es2
. -
slot-successful:<slot-suffix>
. Devuelve "sí" si la ranura dada se ha marcado como arrancando exitosamente, "no" en caso contrario. -
slot-unbootable:<slot-suffix>
. Devuelve "sí" si la ranura dada está marcada como no arrancable, "no" en caso contrario. -
slot-retry-count
. Número de reintentos restantes para intentar iniciar la ranura determinada.
Para ver todas las variables, ejecute fastboot getvar all
.
Generar paquetes OTA
Las herramientas del paquete OTA siguen los mismos comandos que los comandos para dispositivos que no son A/B. El archivo target_files.zip
debe generarse definiendo las variables de compilación para el destino A/B. Las herramientas de paquetes OTA identifican y generan automáticamente paquetes en el formato para el actualizador A/B.
Ejemplos:
- Para generar una OTA completa:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- Para generar una OTA incremental:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configurar particiones
update_engine
puede actualizar cualquier par de particiones A/B definidas en el mismo disco. Un par de particiones tiene un prefijo común (como system
o boot
) y un sufijo por ranura (como _a
). La lista de particiones para las cuales el generador de carga útil define una actualización se configura mediante la variable de creación AB_OTA_PARTITIONS
.
Por ejemplo, si se incluyen un par de particiones bootloader_a
y booloader_b
( _a
y _b
son los sufijos de ranura), puede actualizar estas particiones especificando lo siguiente en la configuración del producto o de la placa:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Todas las particiones actualizadas por update_engine
no deben ser modificadas por el resto del sistema. Durante las actualizaciones incrementales o delta , los datos binarios de la ranura actual se utilizan para generar los datos en la nueva ranura. Cualquier modificación puede hacer que los datos de la nueva ranura no superen la verificación durante el proceso de actualización y, por lo tanto, falle la actualización.
Configurar la postinstalación
Puede configurar el paso posterior a la instalación de manera diferente para cada partición actualizada utilizando un conjunto de pares clave-valor. Para ejecutar un programa ubicado en /system/usr/bin/postinst
en una nueva imagen, especifique la ruta relativa a la raíz del sistema de archivos en la partición del sistema.
Por ejemplo, usr/bin/postinst
es system/usr/bin/postinst
(si no se utiliza un disco RAM). Además, especifique el tipo de sistema de archivos que se pasará a la llamada al sistema mount(2)
. Agregue lo siguiente a los archivos .mk
del producto o dispositivo (si corresponde):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
compilar aplicaciones
Las aplicaciones se pueden compilar en segundo plano antes del reinicio con la nueva imagen del sistema. Para compilar aplicaciones en segundo plano, agregue lo siguiente a la configuración del dispositivo del producto (en el archivo device.mk del producto):
- Incluya los componentes nativos en la compilación para garantizar que el script de compilación y los archivos binarios se compilen e incluyan en la imagen del sistema.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- Conecte el script de compilación a
update_engine
de modo que se ejecute como un paso posterior a la instalación.# 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
Para obtener ayuda con la instalación de los archivos preoptados en la segunda partición del sistema no utilizada, consulte Primera instalación de arranque de archivos DEX_PREOPT .