Menerapkan Pembaruan A/B

Vendor OEM dan SoC yang ingin mengimplementasikan pembaruan sistem A/B harus memastikan bootloader mereka mengimplementasikan boot_control HAL dan meneruskan parameter yang benar ke kernel.

Menerapkan kontrol boot HAL

Bootloader berkemampuan A/B harus mengimplementasikan boot_control HAL di hardware/libhardware/include/hardware/boot_control.h . Anda dapat menguji implementasi menggunakan utilitas system/extras/bootctl dan system/extras/tests/bootloader/ .

Anda juga harus mengimplementasikan mesin negara yang ditunjukkan di bawah ini:

Gambar 1. Mesin status bootloader

Menyiapkan kernel

Untuk menerapkan pembaruan sistem A/B:

  1. Cherrypick seri patch kernel berikut (jika diperlukan):
  2. Pastikan argumen baris perintah kernel berisi argumen tambahan berikut:
    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>"
    ... di mana nilai <public-key-id> adalah ID kunci publik yang digunakan untuk memverifikasi tanda tangan tabel verity (untuk detailnya, lihat dm-verity ) .
  3. Tambahkan sertifikat .X509 yang berisi kunci publik ke gantungan kunci sistem:
    1. Salin sertifikat .X509 yang diformat dalam format .der ke akar direktori kernel . Jika sertifikat .X509 diformat sebagai file .pem , gunakan perintah openssl berikut untuk mengonversi dari format .pem ke .der : l10n
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Bangun zImage untuk menyertakan sertifikat sebagai bagian dari keyring sistem. Untuk memverifikasi, periksa entri procfs (memerlukan KEYS_CONFIG_DEBUG_PROC_KEYS untuk diaktifkan):
      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
      Penyertaan sertifikat .X509 yang berhasil menunjukkan keberadaan kunci publik di keyring sistem (sorotan menunjukkan ID kunci publik).
    3. Ganti spasi dengan # dan berikan sebagai <public-key-id> di baris perintah kernel. Misalnya, teruskan Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f sebagai ganti <public-key-id> .

Mengatur variabel build

Bootloader berkemampuan A/B harus memenuhi kriteria variabel build berikut:

Harus ditentukan untuk target A/B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    dan partisi lain diperbarui melalui update_engine (radio, bootloader, dll.)
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
Sebagai contoh, lihat /device/google/marlin/+/android-7.1.0_r1/device-common.mk . Anda dapat secara opsional melakukan langkah dex2oat pasca-instal (tetapi pra-reboot) yang dijelaskan dalam Compiling .
Sangat direkomendasikan untuk target A/B
  • Tentukan TARGET_NO_RECOVERY := true
  • Definisikan BOARD_USES_RECOVERY_AS_BOOT := true
  • Jangan tentukan BOARD_RECOVERYIMAGE_PARTITION_SIZE
Tidak dapat menentukan target A/B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
Opsional untuk build debug PRODUCT_PACKAGES_DEBUG += update_engine_client

Mengatur partisi (slot)

Perangkat A/B tidak memerlukan partisi pemulihan atau partisi cache karena Android tidak lagi menggunakan partisi ini. Partisi data sekarang digunakan untuk paket OTA yang diunduh, dan kode gambar pemulihan ada di partisi boot. Semua partisi yang A/B-ed harus diberi nama sebagai berikut (slot selalu diberi nama a , b , dll.): boot_a , boot_b , system_a , system_b , vendor_a , vendor_b .

Cache

Untuk pembaruan non-A/B, partisi cache digunakan untuk menyimpan paket OTA yang diunduh dan untuk menyimpan blok sementara saat menerapkan pembaruan. Tidak pernah ada cara yang baik untuk mengukur partisi cache: seberapa besar itu harus bergantung pada pembaruan apa yang ingin Anda terapkan. Kasus terburuk adalah partisi cache sebesar citra sistem. Dengan pembaruan A/B tidak perlu menyimpan blok (karena Anda selalu menulis ke partisi yang saat ini tidak digunakan) dan dengan streaming A/B tidak perlu mengunduh seluruh paket OTA sebelum menerapkannya.

Pemulihan

Disk RAM pemulihan sekarang terdapat dalam file boot.img . Saat masuk ke pemulihan, bootloader tidak dapat menempatkan opsi skip_initramfs pada baris perintah kernel.

Untuk pembaruan non-A/B, partisi pemulihan berisi kode yang digunakan untuk menerapkan pembaruan. Pembaruan A/B diterapkan oleh update_engine yang berjalan di image sistem yang di-boot biasa. Masih ada mode pemulihan yang digunakan untuk menerapkan reset data pabrik dan sideloading paket pembaruan (dari situlah nama "pemulihan" berasal). Kode dan data untuk mode pemulihan disimpan di partisi boot biasa di ramdisk; untuk boot ke citra sistem, bootloader memberi tahu kernel untuk melewati ramdisk (jika tidak, perangkat melakukan boot ke mode pemulihan. Mode pemulihan kecil (dan sebagian besar sudah ada di partisi boot), sehingga partisi boot tidak bertambah dalam ukuran.

Fstab

Argumen slotselect harus berada di baris untuk partisi A/B-ed. Sebagai contoh:

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

Tidak ada partisi yang harus diberi nama vendor . Sebagai gantinya, partisi vendor_a atau vendor_b akan dipilih dan dipasang pada titik pemasangan /vendor .

Argumen slot kernel

Akhiran slot saat ini harus diteruskan melalui node pohon perangkat (DT) tertentu ( /firmware/android/slot_suffix ) atau melalui baris perintah kernel androidboot.slot_suffix atau argumen bootconfig.

Secara default, fastboot mem-flash slot saat ini pada perangkat A/B. Jika paket pembaruan juga berisi gambar untuk slot lain yang tidak aktif, fastboot akan mem-flash gambar tersebut juga. Pilihan yang tersedia meliputi:

  • --slot SLOT . Ganti perilaku default dan minta fastboot untuk mem-flash slot yang diteruskan sebagai argumen.
  • --set-active [ SLOT ] . Atur slot sebagai aktif. Jika tidak ada argumen opsional yang ditentukan, maka slot saat ini disetel sebagai aktif.
  • fastboot --help . Dapatkan detail tentang perintah.

Jika bootloader mengimplementasikan fastboot, bootloader harus mendukung perintah set_active <slot> yang menyetel slot aktif saat ini ke slot yang diberikan (ini juga harus menghapus tanda yang tidak dapat di-boot untuk slot tersebut dan mengatur ulang jumlah percobaan ulang ke nilai default). Bootloader juga harus mendukung variabel berikut:

  • has-slot:<partition-base-name-without-suffix> . Mengembalikan "ya" jika partisi yang diberikan mendukung slot, "tidak" jika tidak.
  • current-slot . Mengembalikan akhiran slot yang akan di-boot dari berikutnya.
  • slot-count . Mengembalikan bilangan bulat yang mewakili jumlah slot yang tersedia. Saat ini, dua slot didukung sehingga nilai ini adalah 2 .
  • slot-successful:<slot-suffix> . Mengembalikan "ya" jika slot yang diberikan telah ditandai sebagai berhasil booting, "tidak" jika tidak.
  • slot-unbootable:<slot-suffix> . Mengembalikan "ya" jika slot yang diberikan ditandai sebagai tidak dapat di-boot, "tidak" jika tidak.
  • slot-retry-count . Jumlah percobaan ulang yang tersisa untuk mencoba mem-boot slot yang diberikan.

Untuk melihat semua variabel, jalankan fastboot getvar all .

Menghasilkan paket OTA

Alat paket OTA mengikuti perintah yang sama dengan perintah untuk perangkat non-A/B. File target_files.zip harus dibuat dengan mendefinisikan variabel build untuk target A/B. Alat paket OTA secara otomatis mengidentifikasi dan menghasilkan paket dalam format untuk pembaru A/B.

Contoh:

  • Untuk menghasilkan OTA penuh:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • Untuk menghasilkan OTA tambahan:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

Mengkonfigurasi partisi

update_engine dapat memperbarui pasangan partisi A/B yang ditentukan dalam disk yang sama. Sepasang partisi memiliki awalan yang sama (seperti system atau boot ) dan akhiran per-slot (seperti _a ). Daftar partisi yang pembaruannya ditentukan oleh generator muatan dikonfigurasi oleh variabel make AB_OTA_PARTITIONS .

Misalnya, jika sepasang partisi bootloader_a dan booloader_b disertakan ( _a dan _b adalah sufiks slot), Anda dapat memperbarui partisi ini dengan menentukan berikut ini pada konfigurasi produk atau papan:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Semua partisi yang diperbarui oleh update_engine tidak boleh dimodifikasi oleh sistem lainnya. Selama pembaruan inkremental atau delta , data biner dari slot saat ini digunakan untuk menghasilkan data di slot baru. Modifikasi apa pun dapat menyebabkan data slot baru gagal verifikasi selama proses pembaruan, dan oleh karena itu gagal pembaruan.

Mengonfigurasi pasca-instalasi

Anda dapat mengonfigurasi langkah pasca-instal secara berbeda untuk setiap partisi yang diperbarui menggunakan satu set pasangan nilai kunci. Untuk menjalankan program yang terletak di /system/usr/bin/postinst dalam gambar baru, tentukan jalur relatif ke akar sistem file di partisi sistem.

Misalnya, usr/bin/postinst adalah system/usr/bin/postinst (jika tidak menggunakan disk RAM). Selain itu, tentukan jenis sistem file yang akan diteruskan ke panggilan sistem mount(2) . Tambahkan yang berikut ini ke file .mk produk atau perangkat (jika ada):

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

kompilasi

Untuk alasan keamanan, system_server tidak dapat menggunakan kompilasi just-in-time (JIT) . Ini berarti Anda harus mengkompilasi file odex sebelumnya untuk system_server dan dependensinya minimal; apa pun adalah opsional.

Untuk mengompilasi aplikasi di latar belakang, Anda harus menambahkan yang berikut ini ke konfigurasi perangkat produk (di device.mk produk):

  1. Sertakan komponen asli dalam build untuk memastikan skrip kompilasi dan binari dikompilasi dan disertakan dalam citra sistem.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Hubungkan skrip kompilasi ke update_engine sedemikian rupa sehingga berjalan sebagai langkah pasca-instal.
      # 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
    

Untuk bantuan dalam menginstal file yang telah dipilih sebelumnya di partisi sistem kedua yang tidak digunakan, lihat Instalasi boot pertama file DEX_PREOPT .