Gli OEM e i fornitori di SoC che desiderano implementare aggiornamenti di sistema A/B devono assicurarsi che il loro bootloader implementi l'HAL boot_control e passi i parametri corretti al kernel.
Implementare l'HAL di controllo di avvio
I bootloader compatibili con A/B devono implementare l'HAL boot_control
in hardware/libhardware/include/hardware/boot_control.h
. È possibile testare le implementazioni utilizzando l'utility system/extras/bootctl
e system/extras/tests/bootloader/
.
È inoltre necessario implementare la macchina a stati mostrata di seguito:
![](https://source.android.google.cn/static/docs/core/ota/images/ab-updates-state-machine.png?authuser=1&hl=it)
Configura il kernel
Per implementare gli aggiornamenti del sistema A/B:
- Scegli la seguente serie di patch del kernel (se necessario):
- Se si esegue l'avvio senza ramdisk e si utilizza "boot as recovery", cherrypick android-review.googlesource.com/#/c/158491/ .
- Per configurare dm-verity senza ramdisk, cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- Assicurati che gli argomenti della riga di comando del kernel contengano i seguenti argomenti aggiuntivi:
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>
è l'ID della chiave pubblica utilizzata per verificare la firma della tabella di verità (per i dettagli, vedere dm-verity ) . - Aggiungi il certificato .X509 contenente la chiave pubblica al portachiavi di sistema:
- Copia il certificato .X509 formattato nel formato
.der
nella radice della directorykernel
. Se il certificato .X509 è formattato come file.pem
, utilizzare il seguente comandoopenssl
per convertire dal formato.pem
al formato.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
- Crea
zImage
per includere il certificato come parte del portachiavi di sistema. Per verificare, controlla la voceprocfs
(richiede cheKEYS_CONFIG_DEBUG_PROC_KEYS
sia abilitato):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
L'inclusione riuscita del certificato .X509 indica la presenza della chiave pubblica nel portachiavi del sistema (l'evidenziazione indica l'ID della chiave pubblica). - Sostituisci lo spazio con
#
e passalo come<public-key-id>
nella riga di comando del kernel. Ad esempio, passaAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
al posto di<public-key-id>
.
- Copia il certificato .X509 formattato nel formato
Imposta le variabili di creazione
I bootloader compatibili con A/B devono soddisfare i seguenti criteri variabili di build:
Deve definire per il target A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Facoltativamente è possibile eseguire il passaggio dex2oat post-installazione (ma pre-riavvio) descritto in Compilazione . |
---|---|
Fortemente consigliato per target A/B |
|
Impossibile definire per il target A/B |
|
Facoltativo per le build di debug | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Imposta partizioni (slot)
I dispositivi A/B non necessitano di una partizione di ripristino o di una partizione cache perché Android non utilizza più queste partizioni. La partizione dati viene ora utilizzata per il pacchetto OTA scaricato e il codice dell'immagine di ripristino si trova nella partizione di avvio. Tutte le partizioni A/B dovrebbero essere denominate come segue (gli slot sono sempre denominati a
, b
, ecc.): boot_a
, boot_b
, system_a
, system_b
, vendor_a
, vendor_b
.
Cache
Per gli aggiornamenti non A/B, la partizione della cache veniva utilizzata per archiviare i pacchetti OTA scaricati e per riporre temporaneamente i blocchi durante l'applicazione degli aggiornamenti. Non c'è mai stato un buon modo per dimensionare la partizione della cache: quanto grande doveva essere dipendeva dagli aggiornamenti che si desidera applicare. Il caso peggiore sarebbe una partizione della cache grande quanto l'immagine del sistema. Con gli aggiornamenti A/B non è necessario memorizzare blocchi (perché si scrive sempre su una partizione che non è attualmente utilizzata) e con lo streaming A/B non è necessario scaricare l'intero pacchetto OTA prima di applicarlo.
Recupero
Il disco RAM di ripristino è ora contenuto nel file boot.img
. Quando si avvia il ripristino, il bootloader non può inserire l'opzione skip_initramfs
sulla riga di comando del kernel.
Per gli aggiornamenti non A/B, la partizione di ripristino contiene il codice utilizzato per applicare gli aggiornamenti. Gli aggiornamenti A/B vengono applicati da update_engine
in esecuzione nella normale immagine del sistema avviato. Esiste ancora una modalità di ripristino utilizzata per implementare il ripristino dei dati di fabbrica e il sideload dei pacchetti di aggiornamento (da cui deriva il nome "ripristino"). Il codice e i dati per la modalità di ripristino vengono archiviati nella normale partizione di avvio in un ramdisk; per eseguire l'avvio nell'immagine di sistema, il bootloader dice al kernel di saltare il ramdisk (altrimenti il dispositivo si avvia in modalità di ripristino. La modalità di ripristino è piccola (e gran parte di essa era già nella partizione di avvio), quindi la partizione di avvio non aumenta in misura.
Fstab
L'argomento slotselect
deve essere sulla riga per le partizioni A/B-ed. Per esempio:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Nessuna partizione deve essere denominata vendor
. Invece, la partizione vendor_a
o vendor_b
verrà selezionata e montata sul punto di montaggio /vendor
.
Argomenti sugli slot del kernel
Il suffisso dello slot corrente deve essere passato tramite un nodo DT (albero dei dispositivi) specifico ( /firmware/android/slot_suffix
) o tramite la riga di comando del kernel androidboot.slot_suffix
o l'argomento bootconfig.
Per impostazione predefinita, l'avvio rapido esegue il flashing dello slot corrente su un dispositivo A/B. Se il pacchetto di aggiornamento contiene anche immagini per l'altro slot non corrente, l'avvio rapido esegue il flashing anche di quelle immagini. Le opzioni disponibili includono:
-
--slot SLOT
. Sostituisci il comportamento predefinito e chiedi a fastboot di eseguire il flashing dello slot passato come argomento. -
--set-active [ SLOT ]
. Imposta lo slot come attivo. Se non viene specificato alcun argomento facoltativo, lo slot corrente viene impostato come attivo. -
fastboot --help
. Ottieni dettagli sui comandi.
Se il bootloader implementa l'avvio rapido, dovrebbe supportare il comando set_active <slot>
che imposta lo slot attivo corrente sullo slot specificato (questo deve anche cancellare il flag non avviabile per quello slot e ripristinare il conteggio dei tentativi sui valori predefiniti). Il bootloader dovrebbe supportare anche le seguenti variabili:
-
has-slot:<partition-base-name-without-suffix>
. Restituisce "sì" se la partizione specificata supporta gli slot, "no" altrimenti. -
current-slot
. Restituisce il suffisso dello slot che verrà avviato successivamente. -
slot-count
. Restituisce un numero intero che rappresenta il numero di slot disponibili. Attualmente sono supportati due slot, quindi questo valore è2
. -
slot-successful:<slot-suffix>
. Restituisce "sì" se lo slot specificato è stato contrassegnato come avvio riuscito, "no" altrimenti. -
slot-unbootable:<slot-suffix>
. Restituisce "sì" se lo slot specificato è contrassegnato come non avviabile, "no" altrimenti. -
slot-retry-count
. Numero di tentativi rimanenti per tentare di avviare lo slot specificato.
Per visualizzare tutte le variabili, esegui fastboot getvar all
.
Genera pacchetti OTA
Gli strumenti del pacchetto OTA seguono gli stessi comandi dei comandi per i dispositivi non A/B. Il file target_files.zip
deve essere generato definendo le variabili di build per la destinazione A/B. Gli strumenti dei pacchetti OTA identificano e generano automaticamente i pacchetti nel formato per l'aggiornamento A/B.
Esempi:
- Per generare un OTA completo:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- Per generare un OTA incrementale:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
Configurare le partizioni
update_engine
può aggiornare qualsiasi coppia di partizioni A/B definite nello stesso disco. Una coppia di partizioni ha un prefisso comune (come system
o boot
) e un suffisso per slot (come _a
). L'elenco delle partizioni per le quali il generatore di payload definisce un aggiornamento è configurato dalla variabile make AB_OTA_PARTITIONS
.
Ad esempio, se sono incluse una coppia di partizioni bootloader_a
e booloader_b
( _a
e _b
sono i suffissi degli slot), è possibile aggiornare queste partizioni specificando quanto segue sulla configurazione del prodotto o della scheda:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Tutte le partizioni aggiornate da update_engine
non devono essere modificate dal resto del sistema. Durante gli aggiornamenti incrementali o delta , i dati binari dello slot corrente vengono utilizzati per generare i dati nel nuovo slot. Qualsiasi modifica potrebbe far sì che i dati del nuovo slot non superino la verifica durante il processo di aggiornamento e, di conseguenza, l'aggiornamento non riesca.
Configura la postinstallazione
È possibile configurare la fase di postinstallazione in modo diverso per ciascuna partizione aggiornata utilizzando un set di coppie chiave-valore. Per eseguire un programma situato in /system/usr/bin/postinst
in una nuova immagine, specificare il percorso relativo alla radice del filesystem nella partizione di sistema.
Ad esempio, usr/bin/postinst
è system/usr/bin/postinst
(se non si utilizza un disco RAM). Inoltre, specificare il tipo di filesystem da passare alla chiamata di sistema mount(2)
. Aggiungi quanto segue ai file .mk
del prodotto o del dispositivo (se applicabile):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Compila app
Le app possono essere compilate in background prima del riavvio con la nuova immagine di sistema. Per compilare le app in background, aggiungi quanto segue alla configurazione del dispositivo del prodotto (nel file device.mk del prodotto):
- Includere i componenti nativi nella build per garantire che lo script di compilazione e i file binari siano compilati e inclusi nell'immagine del sistema.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- Connetti lo script di compilazione a
update_engine
in modo che venga eseguito come passaggio post-installazione.# 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
Per assistenza sull'installazione dei file preoptati nella seconda partizione di sistema non utilizzata, fare riferimento a Installazione al primo avvio dei file DEX_PREOPT .