Producenci OEM i dostawcy SoC, którzy chcą zaimplementować aktualizacje systemu A/B, muszą upewnić się, że ich program ładujący implementuje warstwę HAL boot_control i przekazuje prawidłowe parametry do jądra.
Wdrożenie kontroli rozruchu HAL
Programy ładujące obsługujące A/B muszą zaimplementować warstwę HAL boot_control
w hardware/libhardware/include/hardware/boot_control.h
. Implementacje można testować za pomocą narzędzia system/extras/bootctl
i system/extras/tests/bootloader/
.
Musisz także zaimplementować maszynę stanów pokazaną poniżej:

Konfigurowanie jądra
Aby wdrożyć aktualizacje systemu A/B:
- Cherrypick następujące serie łat jądra (w razie potrzeby):
- W przypadku uruchamiania bez ramdysku i korzystania z opcji „rozruch jako odzyskiwanie”, cherrypick android-review.googlesource.com/#/c/158491/ .
- Aby skonfigurować dm-verity bez ramdysku, cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 .
- Upewnij się, że argumenty wiersza poleceń jądra zawierają następujące 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>"
<public-key-id>
jest identyfikatorem klucza publicznego używanego do weryfikacji podpisu w tabeli Verity (szczegóły znajdziesz w dm-verity ) . - Dodaj certyfikat .X509 zawierający klucz publiczny do pliku kluczy systemowych:
- Skopiuj certyfikat .X509 sformatowany w formacie
.der
do katalogu głównego katalogukernel
. Jeśli certyfikat .X509 jest sformatowany jako plik.pem
, użyj następującego poleceniaopenssl
, aby przekonwertować z.pem
na.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
zImage
, aby dołączyć certyfikat jako część systemowego pliku kluczy. Aby zweryfikować, sprawdź wpisprocfs
(wymagaKEYS_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
Pomyślne włączenie certyfikatu .X509 wskazuje na obecność klucza publicznego w systemowym pęku kluczy (podświetlenie oznacza identyfikator klucza publicznego). - Zastąp spację
#
i przekaż ją jako<public-key-id>
w wierszu poleceń jądra. Na przykład przekażAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
zamiast<public-key-id>
.
- Skopiuj certyfikat .X509 sformatowany w formacie
Ustawianie zmiennych kompilacji
Programy ładujące obsługujące A/B muszą spełniać następujące kryteria zmiennych kompilacji:
Należy zdefiniować dla celu A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . Możesz opcjonalnie wykonać krok po instalacji (ale przed ponownym uruchomieniem) dex2oat opisany w Kompilacja . |
---|---|
Zdecydowanie zalecany do celów A/B |
|
Nie można zdefiniować dla celu A/B |
|
Opcjonalne dla kompilacji debugowania | PRODUCT_PACKAGES_DEBUG += update_engine_client |
Ustawianie partycji (slotów)
Urządzenia A/B nie potrzebują partycji odzyskiwania ani partycji pamięci podręcznej, ponieważ system Android nie używa już tych partycji. Partycja danych jest teraz używana dla pobranego pakietu OTA, a kod obrazu odzyskiwania znajduje się na partycji rozruchowej. Wszystkie partycje w wersji A/B powinny mieć następujące nazwy (sloty 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 i tymczasowego przechowywania bloków podczas stosowania aktualizacji. Nigdy nie było dobrego sposobu na określenie rozmiaru partycji pamięci podręcznej: to, jak duża musi zależeć od tego, jakie aktualizacje chcesz zastosować. Najgorszym przypadkiem byłaby partycja pamięci podręcznej tak duża, jak obraz systemu. Dzięki aktualizacjom A/B nie ma potrzeby przechowywania bloków (ponieważ zawsze piszesz na partycji, która nie jest obecnie używana), a przy strumieniowaniu A/B nie ma potrzeby pobierania całego pakietu OTA przed jego zastosowaniem.
Powrót do zdrowia
Dysk RAM odzyskiwania znajduje się teraz w pliku boot.img
. Podczas odzyskiwania bootloader nie może umieścić opcji skip_initramfs
w wierszu poleceń jądra.
W przypadku aktualizacji innych niż A/B partycja odzyskiwania zawiera kod używany do zastosowania aktualizacji. Aktualizacje A/B są stosowane przez update_engine
uruchomioną w zwykłym obrazie systemu. Nadal istnieje tryb odzyskiwania używany do wdrażania przywracania danych fabrycznych i ładowania bocznego pakietów aktualizacji (stąd nazwa „odzyskiwanie”). Kod i dane do trybu odzyskiwania są przechowywane na zwykłej partycji rozruchowej w ramdysku; aby uruchomić system z obrazu systemu, bootloader mówi jądru, aby pominęło ramdysk (w przeciwnym razie urządzenie uruchomi się w trybie odzyskiwania. Tryb odzyskiwania jest mały (i większość z nich była już na partycji rozruchowej), więc partycja rozruchowa nie zwiększa się W rozmiarze.
Fstab
Argument slotselect
musi znajdować się w wierszu dla partycji A/B-ed. Na przykład:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
Żadna partycja nie powinna być nazwana vendor
. Zamiast tego partycja vendor_a
lub vendor_b
zostanie wybrana i zamontowana w punkcie montowania /vendor
.
Argumenty gniazda jądra
Bieżący sufiks gniazda powinien zostać przekazany przez określony węzeł drzewa urządzeń (DT) ( /firmware/android/slot_suffix
) lub przez wiersz polecenia jądra androidboot.slot_suffix
lub argument bootconfig.
Domyślnie fastboot miga bieżące gniazdo na urządzeniu A/B. Jeśli pakiet aktualizacji zawiera również obrazy dla innego, nieaktualnego gniazda, fastboot również miga te obrazy. Dostępne opcje obejmują:
-
--slot SLOT
. Zastąp domyślne zachowanie i poproś fastboot o flashowanie gniazda, które jest przekazywane jako argument. -
--set-active [ SLOT ]
. Ustaw gniazdo jako aktywne. Jeśli nie określono argumentu opcjonalnego, bieżący slot jest ustawiany jako aktywny. -
fastboot --help
. Uzyskaj szczegółowe informacje na temat poleceń.
Jeśli bootloader implementuje fastboot, powinien obsługiwać polecenie set_active <slot>
, które ustawia bieżące aktywne gniazdo na dane gniazdo (musi to również wyczyścić flagę unbootable dla tego gniazda i zresetować licznik ponownych prób do wartości domyślnych). Bootloader powinien również obsługiwać następujące zmienne:
-
has-slot:<partition-base-name-without-suffix>
. Zwraca „tak”, jeśli dana partycja obsługuje sloty, „nie” w przeciwnym razie. -
current-slot
. Zwraca sufiks slotu, który zostanie uruchomiony od następnego. -
slot-count
. Zwraca liczbę całkowitą reprezentującą liczbę dostępnych gniazd. Obecnie obsługiwane są dwa gniazda, więc ta wartość wynosi2
. -
slot-successful:<slot-suffix>
. Zwraca „tak”, jeśli dany slot został oznaczony jako pomyślnie uruchamiający się, w przeciwnym razie „nie”. -
slot-unbootable:<slot-suffix>
. Zwraca „tak”, jeśli dany slot jest oznaczony jako niebootowalny, „nie” w przeciwnym razie. -
slot-retry-count
. Liczba pozostałych prób uruchomienia danego gniazda.
Aby wyświetlić wszystkie zmienne, uruchom fastboot getvar all
.
Generowanie pakietów OTA
Narzędzia pakietu OTA wykonują te same polecenia, co polecenia dla urządzeń innych niż A/B. Plik target_files.zip
musi zostać wygenerowany przez zdefiniowanie zmiennych kompilacji dla celu A/B. Narzędzia pakietów OTA automatycznie identyfikują i generują pakiety w formacie dla aktualizatora A/B.
Przykłady:
- Aby wygenerować pełną OTA:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip
- Aby wygenerować przyrostowy 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
Konfiguracja partycji
update_engine
może aktualizować dowolną parę partycji A/B zdefiniowanych na tym samym dysku. Para partycji ma wspólny prefiks (taki jak system
lub boot
) i sufiks na gniazdo (taki jak _a
). Lista partycji, dla których generator ładunku definiuje aktualizację, jest konfigurowana przez zmienną make AB_OTA_PARTITIONS
.
Na przykład, jeśli dołączona jest para partycji bootloader_a
i booloader_b
( _a
i _b
są przyrostkami gniazd), możesz zaktualizować te partycje, określając następujące elementy w konfiguracji produktu lub płyty:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
Wszystkie partycje aktualizowane przez update_engine
nie mogą być modyfikowane przez resztę systemu. Podczas aktualizacji przyrostowych lub delta dane binarne z bieżącego gniazda są używane do generowania danych w nowym gnieździe. Wszelkie modyfikacje mogą spowodować, że weryfikacja danych nowego gniazda nie powiodła się podczas procesu aktualizacji, a tym samym nie powiodła się aktualizacja.
Konfiguracja poinstalacyjna
Krok po instalacji można skonfigurować inaczej dla każdej zaktualizowanej partycji, używając zestawu par klucz-wartość. Aby uruchomić program znajdujący się w /system/usr/bin/postinst
w nowym obrazie, określ ścieżkę względem katalogu głównego systemu plików na partycji systemowej.
Na przykład usr/bin/postinst
to system/usr/bin/postinst
(jeśli nie używasz dysku RAM). Dodatkowo określ typ systemu plików, który ma zostać przekazany do wywołania systemowego mount(2)
. Dodaj następujące elementy do plików .mk
produktu lub urządzenia (jeśli dotyczy):
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
Kompilacja
Ze względów bezpieczeństwa system_server
nie może używać kompilacji just-in-time (JIT) . Oznacza to, że musisz skompilować pliki odex z wyprzedzeniem dla serwera system_server
i jego zależności co najmniej; wszystko inne jest opcjonalne.
Aby kompilować aplikacje w tle, należy dodać następujące elementy do konfiguracji urządzenia produktu (w pliku device.mk produktu):
- Dołącz komponenty natywne do kompilacji, aby upewnić się, że skrypt kompilacji i pliki binarne są skompilowane i uwzględnione w obrazie systemu.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- Połącz skrypt kompilacji z
update_engine
tak, aby działał jako krok 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
Aby uzyskać pomoc dotyczącą instalowania wstępnie wybranych plików na nieużywanej drugiej partycji systemowej, zobacz Pierwsza instalacja rozruchowa plików DEX_PREOPT .