Omówienie programu rozruchowego

Program rozruchowy to obraz należący do dostawcy, który odpowiada za uruchomienie jądra na urządzeniu. Program rozruchowy chroni stan urządzenia i odpowiada za inicjowanie zaufanego środowiska wykonawczego (TEE) oraz powiązanie go z głównym źródłem zaufania. Przed przekazaniem wykonania do jądra program rozruchowy sprawdza też integralność partycji boot i recovery.

Przykładowy przepływ programu rozruchowego

Oto przykładowy przepływ programu rozruchowego:

  1. Wczytywanie i inicjowanie pamięci.

  2. Weryfikacja urządzenia zgodnie z procedurą weryfikacji podczas uruchamiania.

  3. Weryfikacja partycji rozruchowych, w tym boot, dtbo, init_boot, i recovery, zgodnie z procedurą weryfikacji podczas uruchamiania. W ramach tego kroku sprawdź wersję nagłówka obrazu rozruchowego i odpowiednio przeanalizuj nagłówek.

  4. Jeśli używane są aktualizacje A/B, określ bieżący slot do uruchomienia.

  5. Określ, czy należy uruchomić tryb odzyskiwania. Więcej informacji znajdziesz w artykule Obsługa aktualizacji OTA.

  6. Wczytaj obrazy rozruchowe, takie jak boot.img, vendor_boot.img, init_boot.img, i inne zastrzeżone obrazy rozruchowe dostawcy. Te obrazy rozruchowe zawierają jądro i obrazy ramdysku.

    1. Wczytaj jądro do pamięci jako samouruchamiający się skompresowany plik binarny. Jądro samo się rozpakowuje i zaczyna wykonywać w pamięci.

    2. Wczytaj ramdyski i sekcję bootconfig do pamięci, aby utworzyć initramfs.

Dodatkowe funkcje związane z programem rozruchowym

Oto lista dodatkowych funkcji związanych z programem rozruchowym, które możesz zaimplementować:

  • Nakładka drzewa urządzeń (DTO). Nakładka drzewa urządzeń umożliwia programowi rozruchowemu obsługę różnych konfiguracji sprzętowych. Nakładka DTO jest kompilowana do blobu drzewa urządzeń (DTB), który jest używany przez program rozruchowy.

  • Randomizacja wirtualnego adresu obrazu jądra. Program rozruchowy obsługuje randomizację wirtualnego adresu, pod którym jest wczytywany obraz jądra. Aby zrandomizować adres, ustaw w konfiguracji jądra wartość RANDOMIZE_BASE na true. Program rozruchowy musi zapewnić entropię, przekazując losową wartość u64 w węźle drzewa urządzeń /chosen/kaslr-seed.

  • Weryfikacja podczas uruchamiania. Weryfikacja podczas uruchamiania umożliwia programowi rozruchowemu sprawdzenie, czy cały wykonywany kod pochodzi z zaufanego źródła.

  • Konfiguracja rozruchu. Konfiguracja rozruchu jest dostępna w Androidzie 12 i nowszych wersjach. Jest to mechanizm przekazywania szczegółów konfiguracji z kompilacji i programu rozruchowego do systemu operacyjnego. W Androidzie 11 i starszych wersjach używane są parametry wiersza poleceń jądra z prefiksem androidboot.

  • Aktualizacje bezprzewodowe (OTA). Urządzenia z Androidem mogą otrzymywać i instalować aktualizacje OTA systemu, oprogramowania aplikacji i reguł stref czasowych. Ta funkcja ma wpływ na implementację programu rozruchowego. Ogólne informacje o aktualizacjach OTA znajdziesz w artykule Aktualizacje OTA. Szczegółowe informacje o implementacji aktualizacji OTA w programie rozruchowym znajdziesz w artykule Obsługa aktualizacji OTA.

  • Powiązanie wersji. Powiązanie wersji wiąże klucze zabezpieczeń z systemem operacyjnym i wersją poziomu poprawek. Powiązanie wersji zapewnia, że atakujący, który odkryje słabość w starszej wersji systemu lub oprogramowania TEE, nie będzie mógł przywrócić urządzenia do podatnej na ataki wersji i użyć kluczy utworzonych w nowszej wersji. Aby obsługiwać powiązanie wersji, program rozruchowy musi udostępniać określone informacje. Więcej informacji znajdziesz w artykule Informacje o wersji we właściwościach AVB.

Wiersz poleceń jądra

Połącz wiersz poleceń jądra z tych lokalizacji:

  • Wiersz poleceń programu rozruchowego: zestaw parametrów statycznych i dynamicznych określonych przez program rozruchowy.

  • Drzewo urządzeń: z węzła chosen/bootargs.

  • defconfig: z CONFIG_CMDLINE.

  • boot.img: z wiersza poleceń (w przypadku przesunięć i rozmiarów zapoznaj się z system/core/mkbootimg/bootimg.h).

W Androidzie 12 w przypadku parametrów androidboot.*, które musimy przekazać do przestrzeni użytkownika Androida, możemy użyć konfiguracji rozruchu zamiast wiersza poleceń jądra.