Implementare gli aggiornamenti A/B

Gli OEM e i fornitori di SoC che vogliono implementare gli aggiornamenti di sistema A/B devono assicurarsi che i loro bootloader implementa l'HAL boot_control e passa i parametri corretti all'interfaccia in un kernel.

Implementazione del controllo di avvio HAL

I bootloader compatibili con A/B devono implementare l'HAL boot_control all'indirizzo hardware/libhardware/include/hardware/boot_control.h. Puoi testare le implementazioni utilizzando system/extras/bootctl utilità e system/extras/tests/bootloader/.

Devi anche implementare la macchina a stati mostrata di seguito:

Figura 1. Macchina a stato bootloader

configura il kernel

Per implementare gli aggiornamenti di sistema A/B:

  1. Seleziona la seguente serie di patch del kernel (se necessario):
  2. 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>"
    ... dove il valore <public-key-id> è l'ID della chiave pubblica utilizzata verificare la firma della tabella di verifica (per maggiori dettagli, vedi verifica dm).
  3. Aggiungi il certificato .X509 contenente la chiave pubblica al keyring del sistema:
    1. Copia il certificato .X509 formattato nel formato .der nella directory principale del Directory kernel. Se il certificato .X509 è formattato come .pem, usa il seguente comando openssl per eseguire la conversione da Formato da .pem a .der:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Crea il zImage per includere il certificato nel keyring del sistema. Per la verifica,controlla la voce procfs (richiede KEYS_CONFIG_DEBUG_PROC_KEYS da attivare):
      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 keyring del sistema (l'evidenziazione indica l'ID della chiave pubblica).
    3. Sostituisci lo spazio con # e passalo come <public-key-id> nella riga di comando del kernel. Ad esempio, trasmetti Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f al posto di <public-key-id>.

Imposta variabili di build

I bootloader compatibili con A/B devono soddisfare i seguenti criteri delle variabili di build:

Da definire per il target A/B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \

      boot \
      system \
      vendor e altre partizioni aggiornate tramite update_engine (radio, bootloader, etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
di Gemini Advanced. Per un esempio, consulta /device/google/marlin/+/android-7.1.0_r1/device-common.mk. Facoltativamente, puoi eseguire il passaggio di dex2oat post-installazione (ma pre-riavvio) descritto in Compilazione.
Fortemente consigliato per il target A/B
  • Definisci TARGET_NO_RECOVERY := true
  • Definisci BOARD_USES_RECOVERY_AS_BOOT := true
  • Non definire BOARD_RECOVERYIMAGE_PARTITION_SIZE
Impossibile definire per il target A/B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
Facoltativo per le build di debug PRODUCT_PACKAGES_DEBUG += update_engine_client

Imposta partizioni (slot)

I dispositivi A/B non hanno bisogno di una partizione di ripristino o cache perché Android non utilizza più da 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 A/B-ed devono essere denominate come segue (gli slot sono sempre denominati a, b e così via): boot_a, boot_b, system_a, system_b e vendor_a vendor_b,

Cache

Per gli aggiornamenti non A/B, la partizione cache veniva utilizzata per archiviare i pacchetti OTA scaricati e per Conserva temporaneamente i blocchi durante l'applicazione degli aggiornamenti. Non è mai esistito un modo valido per dimensionare la cache partizione: le dimensioni necessarie dipendevano dagli aggiornamenti che vuoi applicare. Il peggiore è una partizione cache grande quanto l'immagine di sistema. Grazie agli aggiornamenti A/B non serve per accantonare i blocchi (perché scrivi sempre su una partizione che non è attualmente in uso) con lo streaming A/B non c'è bisogno di scaricare l'intero pacchetto OTA prima di applicarlo.

Ripristino

Il disco RAM di ripristino è ora contenuto nel file boot.img. Quando entri in il bootloader, non può inserire l'opzione skip_initramfs la riga di comando del kernel.

Per gli aggiornamenti non A/B, la partizione di ripristino contiene il codice utilizzato per applicare gli aggiornamenti. A/B gli aggiornamenti vengono applicati da update_engine in esecuzione nella normale immagine di sistema avviata. È ancora presente una modalità di ripristino utilizzata per implementare il ripristino dei dati di fabbrica e il sideload dell'aggiornamento (il nome di "recovery" ("recupero"). Il codice e i dati per la modalità di ripristino sia archiviato nella normale partizione di avvio in un ramdisk; per avviare l'immagine di sistema, bootloader indica al kernel di saltare il ramdisk (altrimenti il dispositivo si avvia in ripristino . La modalità Recovery è ridotta (e in gran parte era già nella partizione di avvio), quindi non aumentano le dimensioni della partizione.

FStab

L'argomento slotselect deve essere sulla riga dell'elemento A/B-ed partizioni di Compute Engine. Ad esempio:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

Nessuna partizione deve essere denominata vendor. Puoi invece eseguire la partizione vendor_a o Verrà selezionato e montato vendor_b sul punto di montaggio /vendor.

Argomenti slot kernel

Il suffisso dello slot attuale deve essere trasmesso tramite un nodo ad albero dei dispositivi (DT) specifico (/firmware/android/slot_suffix) o tramite androidboot.slot_suffix riga di comando del kernel o argomento bootconfig.

Per impostazione predefinita, fastboot lampeggia lo slot corrente su un dispositivo A/B. Se il pacchetto di aggiornamento contiene immagini per l'altro slot non corrente, fastboot esegue anche il flash di queste immagini. Le opzioni disponibili includono:

  • --slot SLOT. Esegui l'override del 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 è presente alcun argomento facoltativo viene specificato, l'area attuale viene impostata come attiva.
  • fastboot --help. Ottieni dettagli sui comandi.

Se il bootloader implementa fastboot, dovrebbe supportare il comando set_active <slot> che imposta l'area attiva corrente sullo slot specificato (questo devi anche cancellare il flag non avviabile per quello slot e reimpostare il numero di nuovi tentativi sul valore predefinito ). Il bootloader dovrebbe supportare anche le seguenti variabili:

  • has-slot:<partition-base-name-without-suffix>. Restituisce "yes" se specificato supporta slot, altrimenti "no".
  • current-slot. Restituisce il suffisso dell'area che verrà avviato dal successivo.
  • 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 l'area specificata è contrassegnato come avvio riuscito, "no" negli altri casi.
  • slot-unbootable:<slot-suffix>. Restituisce "yes" se l'area specificata è contrassegnata come non avviabile, "no" negli altri casi.
  • slot-retry-count:<slot-suffix>. Numero di nuovi tentativi rimanenti per avviare lo slot.

Per visualizzare tutte le variabili, esegui fastboot getvar all.

Genera pacchetti OTA

Gli strumenti del pacchetto OTA seguono gli stessi comandi dei per i dispositivi non A/B. Il file target_files.zip deve essere generato definendo le variabili di build per il target A/B. Gli strumenti dei pacchetti OTA identificano automaticamente e generare pacchetti nel formato del programma di aggiornamento A/B.

Esempi:

  • Per generare un'agenzia di viaggi online completa:
    ./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 definita nello stesso disco. Una coppia di partizioni ha un prefisso comune (ad esempio system o boot) e un suffisso per area (ad esempio _a). L'elenco di partizioni per le quali il payload generatore definisce un aggiornamento configurato dalla variabile make di AB_OTA_PARTITIONS.

Ad esempio, se una coppia di partizioni bootloader_a e Sono inclusi booloader_b (_a e _b sono gli slot i suffissi), puoi aggiornare queste partizioni specificando quanto segue sul prodotto o sulla scheda configurazione:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Tutte le partizioni aggiornate da update_engine non devono essere modificate dal resto del di un sistema operativo completo. Durante gli aggiornamenti incrementali o delta, i dati binari dello slot corrente vengono utilizzata per generare i dati nella nuova area annuncio. Qualsiasi modifica può far sì che i dati della nuova area la verifica non andrà a buon fine durante il processo di aggiornamento e, di conseguenza, l'aggiornamento non andrà a buon fine.

Configura post-installazione

Puoi configurare il passaggio post-installazione in modo diverso per ogni partizione aggiornata utilizzando un set di coppie chiave-valore. Per eseguire un programma disponibile all'indirizzo /system/usr/bin/postinst in una nuova specifica il percorso relativo alla radice del file system nella partizione di sistema.

Ad esempio, usr/bin/postinst è system/usr/bin/postinst (se non utilizzando un disco RAM). Inoltre, specifica il tipo di file system da passare Chiamata di sistema mount(2). Aggiungi quanto segue al prodotto o al dispositivo .mk file (se applicabile):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

Compilazione di 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 device.mk del prodotto):

  1. Includi i componenti nativi nella build 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
    
  2. Collega 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 inutilizzata, consulta Installazione del primo avvio dei file DEX_PREOPT.