Wdrażanie aktualizacji typu A/B

OEM i dostawcy układów SoC, którzy chcą wdrożyć aktualizacje systemu A/B, muszą zapewnić swój program rozruchowy. implementuje kod HAL Boot_control i przekazuje prawidłowe parametry do jądro.

Wdrażanie HAL kontroli rozruchu

Programy rozruchowe z obsługą A/B muszą implementować kod HAL boot_control w hardware/libhardware/include/hardware/boot_control.h Możesz testować implementacje za pomocą system/extras/bootctl użyteczność system/extras/tests/bootloader/

Musisz też wdrożyć maszynę stanu widoczną poniżej:

Rysunek 1. Maszyna stanu programu rozruchowego

Konfigurowanie jądra systemu

Aby wdrożyć aktualizacje systemu A/B:

  1. Cherrypick: wybierz tę serię poprawek jądra (w razie potrzeby):
  2. Sprawdź, czy argumenty wiersza poleceń jądra zawierają te dodatkowe argumenty:
    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>"
    ... gdzie wartość <public-key-id> jest identyfikatorem klucza publicznego używanego do zweryfikować podpis w tabeli Verity (szczegółowe informacje znajdziesz w artykule dm-verity).
  3. Dodaj certyfikat .X509 zawierający klucz publiczny do systemowego pęku kluczy:
    1. Skopiuj certyfikat .X509 sformatowany w formacie .der do katalogu głównego kernel. Jeśli certyfikat X509 ma format .pem, użyj tego polecenia openssl, aby dokonać konwersji z Format od .pem do .der:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. Skompiluj zImage, aby uwzględnić certyfikat w systemowym pęku kluczy. Aby to sprawdzić,sprawdź wpis procfs (wymaga KEYS_CONFIG_DEBUG_PROC_KEYS):
      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
      Uwzględnienie certyfikatu .X509 oznacza obecność klucza publicznego w pęku kluczy systemu (wyróżnienie oznacza identyfikator klucza publicznego).
    3. Zastąp pokój słowem # i przekaż go jako <public-key-id> w wierszu poleceń jądra. Na przykład: Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f w miejscu <public-key-id>

Ustawianie zmiennych kompilacji

Programy rozruchowe z obsługą A/B muszą spełniać te kryteria zmiennej kompilacji:

Musisz zdefiniować dla celu A/B
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \,
      boot \

      system \
      vendor i inne partycje zaktualizowane przez update_engine (radio, program rozruchowy, etc.)
  • PRODUCT_PACKAGES += \
      update_engine \
      update_verifier
. Na przykład: /device/google/marlin/+/android-7.1.0_r1/device-common.mk Opcjonalnie możesz przeprowadzić krok dex2oat po instalacji (ale przed zrestartowaniem) opisany w Kompiluję.
Zdecydowanie zalecany dla celu A/B
  • Podaj definicję słowa TARGET_NO_RECOVERY := true
  • Podaj definicję słowa BOARD_USES_RECOVERY_AS_BOOT := true
  • Nie definiuj pola BOARD_RECOVERYIMAGE_PARTITION_SIZE
Nie można zdefiniować dla celu A/B
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
Opcjonalny w przypadku kompilacji do debugowania PRODUCT_PACKAGES_DEBUG += update_engine_client

Ustaw partycje (przedziały)

Urządzenia A/B nie potrzebują partycji odzyskiwania ani pamięci podręcznej, ponieważ Android nie używa już tych partycji. Partycja danych jest teraz używana dla pobranego pakietu OTA, a na partycji rozruchowej. Wszystkie partycje, które są typu A/B-ed, powinny mieć nazwę. w następujący sposób (boksy są zawsze nazywane a, b itd.): boot_a, boot_b, system_a, system_b, vendor_a vendor_b.

Pamięć podręczna

W przypadku aktualizacji innych niż A/B partycja pamięci podręcznej była używana do przechowywania pobranych pakietów OTA oraz do tymczasowego przechowywania danych. Nigdy nie było odpowiedniego rozmiaru pamięci podręcznej partycji: jak duży rozmiar zależy od aktualizacji, które chcesz zastosować. Najgorsze jest partycja pamięci podręcznej tak duża, jak obraz systemu. Dzięki aktualizacjom typu A/B nie trzeba do przechowywania bloków (ponieważ zawsze piszesz na partycji, która nie jest obecnie używana) i w przypadku strumieniowania A/B nie trzeba pobierać całego pakietu OTA przed jego zastosowaniem.

Odzyskanie

Dysk RAM odzyskiwania jest teraz zawarty w pliku boot.img. Gdy przechodzisz do program rozruchowy nie może włączyć opcji skip_initramfs w wierszu poleceń jądra systemu operacyjnego.

W przypadku aktualizacji innych niż A/B partycja odzyskiwania zawiera kod używany do ich stosowania. A/B aktualizacje są stosowane przez oprogramowanie update_engine uruchomione w zwykłym obrazie systemu po rozruchu. Nadal istnieje tryb przywracania używany do przywracania danych fabrycznych i instalowania aktualizacji z nieoficjalnych źródeł pakiety (od tego pochodzi nazwa „recovery”). kod i dane trybu przywracania; jest przechowywana na zwykłej partycji rozruchowej na dysku ramdisk; do obrazu systemu, program rozruchowy informuje jądro o pominięciu pamięci RAM (w przeciwnym razie urządzenie uruchamia się w trybie przywracania). i trybu uzyskiwania zgody. Tryb przywracania jest mały (większość znajdowała się już na partycji rozruchowej), więc system partycja się nie powiększa.

FSTab

Argument slotselect musi znajdować się w wierszu argumentu A/B-ed. partycji. Na przykład:

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

Żadna partycja nie powinna mieć nazwy vendor. Zamiast tego partycjonuj: vendor_a lub Usługa vendor_b zostanie wybrana i podłączona w punkcie podłączania /vendor.

Argumenty boksu jądra

Bieżący sufiks przedziału należy przekazać przez określony węzeł drzewa urządzenia (DT) (/firmware/android/slot_suffix) lub przez androidboot.slot_suffix wiersza poleceń jądra lub argument rozruchowy.

Domyślnie fastboot miga do bieżącego gniazda na urządzeniu A/B. Jeśli pakiet aktualizacji również zawiera obrazy dla drugiego, nieaktualnego boksu, fastboot również wyświetla te obrazy. Dostępne opcje:

  • --slot SLOT. Zastąp domyślne zachowanie i wyświetlaj szybki rozruch w celu załadowania do gniazda, które jest przekazywane jako argument.
  • --set-active [SLOT]. Ustaw przedział jako aktywny. Jeśli nie ma opcjonalnego argumentu , obecny przedział zostanie ustawiony jako aktywny.
  • fastboot --help Dowiedz się więcej o poleceniach.

Jeśli program rozruchowy wdraża szybki rozruch, powinien obsługiwać polecenie set_active <slot> ustawia bieżący aktywny przedział na dane musi też usunąć flagę braku rozruchu tego przedziału i zresetować liczbę ponownych prób do wartości domyślnej ). Program rozruchowy powinien też obsługiwać te zmienne:

  • has-slot:<partition-base-name-without-suffix>. Zwraca wartość „yes”, jeśli podano partycja obsługuje przedziały, w przeciwnym razie „no”.
  • current-slot Zwraca sufiks przedziału, który będzie uruchamiany od następnego.
  • slot-count. Zwraca liczbę całkowitą reprezentującą liczbę dostępnych przedziałów. Obecnie obsługiwane są 2 przedziały, więc ta wartość wynosi 2.
  • slot-successful:<slot-suffix>. Zwraca wartość „yes” (tak) jeśli dany przedział został oznaczono jako uruchamianie, komunikat „no” (nie) w przeciwnym razie.
  • slot-unbootable:<slot-suffix>. Zwraca wartość „yes”, jeśli dany boks jest oznaczony jako unbooable, "no" w przeciwnym razie.
  • slot-retry-count:<slot-suffix>. Liczba pozostałych ponownych prób uruchomić dany gniazdo.

Aby wyświetlić wszystkie zmienne, uruchom polecenie fastboot getvar all

Generuj pakiety OTA

Narzędzia pakietu OTA działają zgodnie z tymi samymi poleceniami co na urządzeniach innych niż A/B. Plik target_files.zip musi zostać wygenerowany przez które definiują zmienne kompilacji dla celu A/B. Narzędzia pakietu OTA automatycznie identyfikują i generuj pakiety w formacie przeznaczonym dla aktualizatora A/B.

Przykłady:

  • Aby wygenerować pełną wersję OTA:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.zip
    
  • Aby wygenerować przyrostową aktualizację OTA:
    ./build/make/tools/releasetools/ota_from_target_files \
        -i PREVIOUS-tardis-target_files.zip \
        dist_output/tardis-target_files.zip \
        incremental_ota_update.zip
    

Skonfiguruj partycje

update_engine może aktualizować dowolną parę partycji A/B zdefiniowanych na tym samym dysku. Para partycji ma wspólny prefiks (np. system lub boot) i sufiks według boksu (np. _a). Lista partycji, dla których ładunek generator określa, że aktualizacja jest konfigurowana przez zmienną AB_OTA_PARTITIONS Make.

Na przykład, jeśli para partycji bootloader_a i Uwzględniane są booloader_b (_a i _b to przedział czasu) sufiksy), możesz zaktualizować te partycje, określając w produkcie lub na tablicy Konfiguracja:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

Żadne partycje zaktualizowane przez zasadę update_engine nie mogą być modyfikowane przez resztę systemu. Podczas aktualizacji przyrostowych (delta) dane binarne z bieżącego przedziału są wykorzystane do wygenerowania danych w nowym boksie. Każda modyfikacja może spowodować, że dane nowego przedziału nie powiedzie się podczas procesu aktualizacji, a w efekcie aktualizacja zakończy się niepowodzeniem.

Skonfiguruj poinstalację

Możesz skonfigurować krok po instalacji inaczej dla każdej zaktualizowanej partycji, używając zestawu par klucz-wartość. Aby uruchomić program zlokalizowany pod adresem /system/usr/bin/postinst w nowym image, określ ścieżkę względną wobec katalogu głównego systemu plików na partycji systemowej.

Na przykład usr/bin/postinst to system/usr/bin/postinst (jeśli nie za pomocą dysku RAM). Określ też typ systemu plików, który chcesz przekazać do mount(2) wywołanie systemowe. Dodaj do produktu lub urządzenia następujące elementy .mk plików (jeśli dotyczy):

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

Kompilowanie aplikacji

Aplikacje mogą być kompilowane w tle przed ponownym uruchomieniem z nowym obrazem systemu. Kompilowanie aplikacji w tle, dodaj do konfiguracji urządzenia: product's device.mk):

  1. Uwzględnij w kompilacji komponenty natywne, aby skrypt kompilacji i pliki binarne skompilować i umieścić w obrazie systemu.
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. Połącz skrypt kompilacji z elementem update_engine, który będzie działać jako po instalacji.
      # 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
    

Pomoc dotycząca instalowania gotowych plików w nieużywanej drugiej partycji systemowej znajdziesz tutaj: Instalacja plików DEX_PREOPT przy pierwszym rozruchu.