Los OEM y los proveedores de SoC que deseen implementar actualizaciones del sistema A/B deben asegurarse de que su bootloader implemente la HAL de boot_control y pase los parámetros correctos al kernel.
Implementa la HAL de control de arranque
Los bootloaders compatibles con A/B deben implementar la HAL de boot_control en
hardware/libhardware/include/hardware/boot_control.h. Puedes probar las implementaciones con la
system/extras/bootctl
utilidad y
system/extras/tests/bootloader/.
También debes implementar la máquina de estados que se muestra a continuación:
Configura el kernel
Para implementar actualizaciones del sistema A/B, haz lo siguiente:
-
Selecciona los mejores elementos de la siguiente serie de parches del kernel (si es necesario):
- Si inicias sin ramdisk y usas "boot as recovery", selecciona android-review.googlesource.com/#/c/158491/.
- Para configurar dm-verity sin ramdisk, selecciona android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18.
-
Asegúrate de que los argumentos de la línea de comandos del kernel contengan los siguientes argumentos adicionales:
... donde el valorskip_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 que se usa para verificar la firma de la tabla de verity (para obtener más detalles, consulta dm-verity). -
Agrega el certificado .X509 que contiene la clave pública al llavero del sistema:
-
Copia el certificado .X509 con formato
.deren la raíz delkerneldirectorio. Si el certificado .X509 tiene formato de archivo.pemusa el siguienteopensslpara convertirlo de.pema.derformato:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Compila
zImagepara incluir el certificado como parte del llavero del sistema. Para verificar,consulta la entradaprocfs(requiereKEYS_CONFIG_DEBUG_PROC_KEYSque se habilite): La inclusión correcta del certificado .X509 indica la presencia de la clave pública en el llavero del sistema (el resaltado indica el ID de la clave pública).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
-
Reemplaza el espacio por
#y pásalo como<public-key-id>en la línea de comandos del kernel. Por ejemplo, pasaAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40fen lugar de<public-key-id>.
-
Copia el certificado .X509 con formato
Establece variables de compilación
Los bootloaders compatibles con A/B deben cumplir con los siguientes criterios de variables de compilación:
| Debe definirse para el destino A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk. De manera opcional, puedes realizar el paso dex2oat posterior a la instalación (pero anterior al reinicio) que se describe en
Compilación.
|
|---|---|
| Muy recomendado para el destino A/B |
|
| No se puede definir para el destino A/B |
|
| Opcional para compilaciones de depuración | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Establece particiones (espacios)
Los dispositivos A/B no necesitan una partición de recuperación ni una partición de caché porque Android ya no usa
estas particiones. Ahora, la partición de datos se usa para el paquete OTA descargado, y el
código de la imagen de recuperación está en la partición de arranque. Todas las particiones que son A/B deben nombrarse
de la siguiente manera (los espacios siempre se denominan a, b, etc.): boot_a,
boot_b, system_a, system_b, vendor_a,
vendor_b.
Caché
Para las actualizaciones que no son A/B, la partición de caché se usaba para almacenar paquetes OTA descargados y para ocultar bloques de forma temporal mientras se aplicaban las actualizaciones. Nunca hubo una buena manera de dimensionar la partición de caché: el tamaño que necesitaba dependía de las actualizaciones que querías aplicar. En el peor de los casos, la partición de caché sería tan grande como la imagen del sistema. Con las actualizaciones A/B, no es necesario ocultar bloques (porque siempre escribes en una partición que no se usa actualmente) y con A/B de transmisión, no es necesario descargar todo el paquete OTA antes de aplicarlo.
Recuperación
El disco RAM de recuperación ahora está contenido en el archivo boot.img. Cuando se ingresa a
la recuperación, el bootloader no puede colocar la opción skip_initramfs en
la línea de comandos del kernel.
Para las actualizaciones que no son A/B, la partición de recuperación contiene el código que se usa para aplicar actualizaciones. `update_engine` aplica las actualizaciones A/B
que se ejecutan en la imagen del sistema iniciada de forma normal.update_engine
Aún existe un modo de recuperación que se usa para implementar el restablecimiento de datos de configuración de fábrica y la transferencia de paquetes de actualización (de ahí proviene el nombre "recuperación"). El código y los datos del modo de recuperación
se almacenan en la partición de arranque normal en un disco RAM. Para iniciar la imagen del sistema, el
bootloader le indica al kernel que omita el disco RAM (de lo contrario, el dispositivo se inicia en el modo de recuperación
mode. El modo de recuperación es pequeño (y gran parte ya estaba en la partición de arranque), por lo que el tamaño de la partición de arranque no aumenta.
Fstab
El argumento slotselect debe estar en la línea de las particiones A/B. Por ejemplo:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Ninguna partición debe llamarse vendor. En cambio, se seleccionará y activará la partición vendor_a o
vendor_b en el punto de activación /vendor.
Argumentos de espacio del kernel
El sufijo de espacio actual debe pasarse a través de un nodo específico del árbol de dispositivos (DT)
(/firmware/android/slot_suffix) o a través de la
androidboot.slot_suffix línea de comandos del kernel o el argumento de bootconfig.
De forma predeterminada, fastboot actualiza el espacio actual en un dispositivo A/B. Si el paquete de actualización también contiene imágenes para el otro espacio no actual, fastboot también actualiza esas imágenes. Las opciones disponibles incluyen las siguientes:
-
--slot SLOT. Anula el comportamiento predeterminado y solicita a fastboot que escriba en la memoria flash el espacio que se pasa como argumento. -
--set-active [SLOT]. Establece el espacio como activo. Si no se especifica ningún argumento opcional, el espacio actual se establece como activo. fastboot --help. Obtén detalles sobre los comandos.
Si el bootloader implementa fastboot, debe admitir el comando
set_active <slot> que establece el espacio activo actual en el espacio determinado (esto
también debe borrar la marca no iniciable para ese espacio y restablecer el recuento de reintentos a los valores predeterminados). El bootloader también debe admitir las siguientes variables:
-
has-slot:<partition-base-name-without-suffix>. Muestra "yes" si la partición determinada admite espacios y "no" en caso contrario. current-slot. Muestra el sufijo de espacio desde el que se iniciará a continuación.-
slot-count. Muestra un número entero que representa la cantidad de espacios disponibles. Actualmente, se admiten dos espacios, por lo que este valor es2. -
slot-successful:<slot-suffix>. Muestra "yes" si el espacio determinado se marcó como inicio correcto y "no" en caso contrario. -
slot-unbootable:<slot-suffix>. Muestra "yes" si el espacio determinado se marcó como no iniciable y "no" en caso contrario. -
slot-retry-count:<slot-suffix>. Es la cantidad de reintentos restantes para intentar iniciar el espacio determinado.
Para ver todas las variables, ejecuta
fastboot getvar all.
Genera 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 del paquete OTA identifican automáticamente
y generan paquetes en el formato para el actualizador A/B.
Ejemplos:
-
Para generar un OTA completo, haz lo siguiente:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip -
Para generar un OTA incremental, haz lo siguiente:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configura 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 espacio (como _a). La lista de particiones para las que el generador de carga útil
define una actualización se configura con la variable de creación AB_OTA_PARTITIONS.
Por ejemplo, si se incluye un par de particiones bootloader_a y
booloader_b (_a y _b son los sufijos de espacio), puedes actualizar estas particiones especificando lo siguiente en la configuración del producto o la placa:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
El resto del
sistema no debe modificar ninguna de las particiones actualizadas por update_engine. Durante las actualizaciones incrementales o delta, los datos binarios del espacio actual se
usan para generar los datos en el espacio nuevo. Cualquier modificación puede hacer que los datos del espacio nuevo no pasen la verificación durante el proceso de actualización y, por lo tanto, que falle la actualización.
Configura la instalación posterior
Puedes configurar el paso de instalación posterior de manera diferente para cada partición actualizada con un conjunto de
pares clave-valor. Para ejecutar un programa ubicado en /system/usr/bin/postinst en una imagen nueva, especifica la ruta de acceso 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
usas un disco RAM). Además, especifica el tipo de sistema de archivos para pasar a la
mount(2) llamada al sistema. Agrega 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
Compila apps
Las apps se pueden compilar en segundo plano antes del reinicio con la nueva imagen del sistema. Para compilar apps en segundo plano, agrega lo siguiente a la configuración del dispositivo del producto (en el device.mk del producto):
-
Incluye los componentes nativos en la compilación para garantizar que la secuencia de comandos de compilación y los archivos binarios se
compilen y se incluyan en la imagen del sistema.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Conecta la secuencia de comandos de compilación a
update_enginepara 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 para instalar los archivos preoptimizados en la segunda partición del sistema sin usar, consulta Instalación de inicio de archivos DEX_PREOPT.