Gli OEM e i fornitori di SoC che vogliono implementare gli aggiornamenti di sistema A/B devono assicurarsi che il bootloader implementi l'HAL boot_control e trasmetta i parametri corretti al kernel.
Implementa l'HAL di controllo dell'avvio
I bootloader compatibili con A/B devono implementare l'HAL boot_control
in
hardware/libhardware/include/hardware/boot_control.h
. Puoi testare le implementazioni utilizzando l'utilità
system/extras/bootctl
e
system/extras/tests/bootloader/
.
Devi anche implementare la macchina a stati mostrata di seguito:

Configurare il kernel
Per implementare gli aggiornamenti di sistema A/B:
-
Scegli le seguenti serie di patch del kernel (se necessario):
- Se avvii senza ramdisk e utilizzi "boot as recovery", scegli manualmente android-review.googlesource.com/#/c/158491/.
- Per configurare dm-verity senza ramdisk, esegui il cherry-pick 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 extra:
dove il valoreskip_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 Verity (per maggiori dettagli, consulta dm-verity). -
Aggiungi il certificato .X509 contenente la chiave pubblica al portachiavi di sistema:
-
Copia il certificato .X509 formattato nel formato
.der
nella directory principale della directorykernel
. Se il certificato .X509 è formattato come file.pem
, utilizza il seguente comandoopenssl
per eseguire la conversione da.pem
a.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
Crea
zImage
per includere il certificato nel portachiavi di sistema. Per verificare,controlla la voceprocfs
(è necessario attivareKEYS_CONFIG_DEBUG_PROC_KEYS
): Se l'inclusione del certificato .X509 è andata a buon fine, significa che la chiave pubblica è presente nel portachiavi di sistema (l'evidenziazione indica l'ID chiave pubblica).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
-
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
Impostare le variabili di compilazione
I bootloader compatibili con A/B devono soddisfare i seguenti criteri per le variabili di compilazione:
Deve essere definito per il target A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Se vuoi, puoi eseguire il passaggio dex2oat post-installazione (ma prima del riavvio) descritto in
Compilazione.
|
---|---|
Vivamente consigliato per il target A/B |
|
Impossibile definire il target A/B |
|
Facoltativo per le build di debug | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Impostare le partizioni (slot)
I dispositivi A/B non richiedono una partizione di ripristino o una partizione della cache perché Android non utilizza più queste partizioni. La partizione dei 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 sottoposte a test A/B devono essere denominate
come segue (gli slot sono sempre denominati a
, b
e così via): 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 nascondere temporaneamente i blocchi durante l'applicazione degli aggiornamenti. Non è mai stato possibile determinare in modo ottimale le dimensioni della partizione della cache: la dimensione dipendeva dagli aggiornamenti che volevi applicare. Il peggiore caso sarebbe una partizione della cache delle dimensioni dell'immagine di sistema. Con gli aggiornamenti A/B non è necessario nascondere i blocchi (poiché scrivi sempre in una partizione non attualmente in uso) e con lo streaming A/B non è necessario scaricare l'intero pacchetto OTA prima di applicarlo.
Ripristino
Il disco RAM di ripristino è ora contenuto nel file boot.img
. Quando si accede al recupero, il bootloader non può inserire l'opzione skip_initramfs
nella 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 nell'immagine di sistema di avvio normale.
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 "recovery"). Il codice e i dati per la modalità di recupero
vengono memorizzati nella partizione di avvio normale in un ramdisk; per avviare l'immagine di sistema, il bootloader invita il kernel a saltare il ramdisk (in caso contrario il dispositivo si avvia in modalità di recupero. La modalità di ripristino è di piccole dimensioni (e gran parte di essa era già presente nella partizione di avvio), pertanto le dimensioni della partizione di avvio non aumentano.
Fstab
L'argomento slotselect
deve trovarsi nella riga per le partizioni sperimentali A/B. Ad esempio:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Nessuna partizione deve avere il nome vendor
. Al suo posto, la partizione vendor_a
o
vendor_b
verrà selezionata e montata sul punto di montaggio /vendor
.
Argomenti dello slot del kernel
Il suffisso dell'attuale slot deve essere passato tramite un nodo DT (Device Tree) specifico
(/firmware/android/slot_suffix
) o tramite la riga di comando del kernel o l'argomento bootconfig
androidboot.slot_suffix
.
Per impostazione predefinita, fastboot 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, fastboot esegue il flashing anche di queste immagini. Le opzioni disponibili sono:
-
--slot SLOT
. Sostituisci il comportamento predefinito e chiedi a fastboot di eseguire il flashing dello slot passato come un 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
. Visualizza i dettagli dei comandi.
Se il bootloader implementa fastboot, deve supportare il comando
set_active <slot>
che imposta lo slot attivo corrente sullo slot specificato (questo deve anche cancellare il flag unbootable per lo slot e reimpostare il conteggio dei tentativi sui valori predefiniti). Il bootloader deve supportare anche le seguenti variabili:
-
has-slot:<partition-base-name-without-suffix>
. Restituisce "yes" se la partizione specificata supporta gli slot, "no" in caso contrario. current-slot
. Restituisce il suffisso dello slot da cui verrà eseguito il successivo avvio.-
slot-count
. Restituisce un numero intero che rappresenta il numero di slot disponibili. Al momento sono supportati due slot, quindi questo valore è2
. -
slot-successful:<slot-suffix>
. Restituisce "yes" se lo slot specificato è stato contrassegnato come avviato correttamente, "no" in caso contrario. -
slot-unbootable:<slot-suffix>
. Restituisce "yes" se lo slot specificato è contrassegnato come non avviabile, "no" in caso contrario. -
slot-retry-count:<slot-suffix>
. Numero di tentativi rimanenti per avviare lo slot specificato.
Per visualizzare tutte le variabili, esegui
fastboot getvar all
.
Generare pacchetti OTA
Gli strumenti per i pacchetti 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 compilazione per il target A/B. Gli strumenti per i pacchetti OTA identificano automaticamente
e generano 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
Configura le partizioni
update_engine
può aggiornare qualsiasi coppia di partizioni A/B definite nello stesso disco.
Una coppia di partizioni ha un prefisso comune (ad esempio system
o boot
)
e un suffisso per slot (ad esempio _a
). L'elenco delle partizioni per le quali il generatore di payload
definisce un aggiornamento è configurato dalla variabile di creazione AB_OTA_PARTITIONS
.
Ad esempio, se è inclusa una coppia di partizioni bootloader_a
e
booloader_b
(_a
e _b
sono i suffissi
della scheda), puoi aggiornarle specificando quanto segue nella 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 causare la mancata verifica dei dati del nuovo slot durante la procedura di aggiornamento e, di conseguenza, l'aggiornamento non andrà a buon fine.
Configura postinstallazione
Puoi configurare il passaggio di postinstallazione in modo diverso per ogni partizione aggiornata utilizzando un insieme di
coppie chiave-valore. Per eseguire un programma in /system/usr/bin/postinst
in una nuova
immagine, specifica il percorso relativo alla radice del file system nella partizione di sistema.
Ad esempio, usr/bin/postinst
è system/usr/bin/postinst
(se non
utilizzi un disco RAM). Inoltre, specifica il tipo di file system 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
Compilare le 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):
-
Includi i componenti nativi nella compilazione per assicurarti che lo script di compilazione e i file binari vengano compilati e inclusi nell'immagine di sistema.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
Collega lo script di compilazione a
update_engine
in modo che venga eseguito come passaggio di 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 pre-optati nella seconda partizione di sistema inutilizzata, consulta Installazione al primo avvio dei file DEX_PREOPT.