Budowanie jąder

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Na tej stronie szczegółowo opisano proces tworzenia niestandardowych jąder dla urządzeń z systemem Android. Te instrukcje poprowadzą Cię przez proces wyboru odpowiednich źródeł, budowania jądra i osadzania wyników w obrazie systemu zbudowanym na podstawie projektu Android Open Source Project (AOSP).

Nowsze źródła jądra można uzyskać za pomocą Repo ; skompiluj je bez dalszej konfiguracji, uruchamiając build/build.sh z katalogu głównego swojego źródła.

Pobieranie źródeł i narzędzi do budowania

W przypadku najnowszych jąder użyj repo , aby pobrać źródła, łańcuch narzędzi i kompilować skrypty. Niektóre jądra (na przykład jądra Pixel 3) wymagają źródeł z wielu repozytoriów git, podczas gdy inne (na przykład wspólne jądra) wymagają tylko jednego źródła. Korzystanie z podejścia repo zapewnia poprawną konfigurację katalogu źródłowego.

Pobierz źródła dla odpowiedniego oddziału:

mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b BRANCH
repo sync

W poniższej tabeli wymieniono nazwy BRANCH dla jąder dostępnych za pomocą tej metody.

Urządzenie Ścieżka binarna w drzewie AOSP Oddziały repo
Piksel 6a (niebieski sójka) urządzenie/google/jądro-bluejay android-gs-bluejay-5.10-android13
Piksel 6 (wilga)
Pixel 6 Pro (kruk)
urządzenie/google/raviole-kernel android-gs-raviole-5.10-android13
Piksel 5a (barbet) urządzenie/google/barbet-jądro android-msm-barbet-4.19-android13
Piksel 5 (czerwony)
Piksel 4a (5G) (bramka)
urządzenie/google/jądro-redbull android-msm-redbull-4.19-android13
Piksel 4a (samogłów) urządzenie/google/jądro sunfish android-msm-sunfish-4.14-android13
Piksel 4 (płomień)
Pixel 4 XL (koralowy)
urządzenie/google/koral-jądro android-msm-coral-4.14-android13
Piksel 3a (sargo)
Pixel 3a XL (bonito)
urządzenie/google/jądro-bonito android-msm-bonito-4.9-android12L
Piksel 3 (niebieska linia)
Pixel 3 XL (kreskowany)
urządzenie/google/krzyżowane jądro android-msm-krzyżówka-4.9-android12
Piksel 2 (walleye)
Pixel 2 XL (taimen)
urządzenie/google/wahoo-jądro android-msm-wahoo-4.4-android10-qpr3
Piksel (żaglówka)
Piksel XL (marlin)
urządzenie/google/jądro-marlin android-msm-marlin-3.18-pie-qpr2
Hikey960 urządzenie/linaro/hikey-jądro wycieczka-linaro-android-4.14
wycieczka-linaro-android-4.19
wspólny-android12-5.4
Beagle x15 urządzenie/ti/beagle_x15-jądro omap-beagle-x15-android-4.14
omap-beagle-x15-android-4.19
Wspólne jądro systemu Android Nie dotyczy wspólny-android-4.4
wspólny-android-4.9
wspólny-android-4.14
wspólny-android-4.19
wspólny-android-4.19-stabilny
wspólny-android11-5.4
wspólny-android12-5.4
wspólny-android12-5.10
wspólny-android13-5.10
wspólny-android13-5.15
wspólny-android-główny

Budowanie jądra

Następnie zbuduj jądro za pomocą tego:

build/build.sh

Plik binarny jądra, moduły i odpowiadający im obraz znajdują się w katalogu out/ BRANCH /dist .

Budynek z Bazel (Kleaf)

Android 13 wprowadził budowanie jąder za pomocą Bazel , zastępując build/build.sh .

Aby zbudować jądro GKI dla architektury aarch64, uruchom:

tools/bazel build //common:kernel_aarch64_dist

Aby utworzyć dystrybucję, uruchom:

tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR

Następnie plik binarny jądra, moduły i odpowiadające im obrazy znajdują się w katalogu $DIST_DIR . Jeśli --dist_dir nie jest określone, zobacz dane wyjściowe polecenia, aby sprawdzić lokalizację artefaktów. Aby uzyskać szczegółowe informacje, zapoznaj się z dokumentacją dotyczącą AOSP .

Budowanie modułów GKI

Android 11 wprowadził GKI , który rozdziela jądro na obraz jądra obsługiwany przez Google i obsługiwane przez dostawcę moduły, które są budowane osobno.

Ten przykład pokazuje konfigurację obrazu jądra:

BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh

Ten przykład pokazuje konfigurację modułu (mątwa i emulator):

BUILD_CONFIG=common-modules/virtual-device/build.config.cuttlefish.x86_64 build/build.sh

W systemie Android 12 Cuttlefish i Goldfish są zbieżne, więc mają to samo jądro: virtual_device . Aby zbudować moduły tego jądra, użyj tej konfiguracji kompilacji:

BUILD_CONFIG=common-modules/virtual-device/build.config.virtual_device.x86_64 build/build.sh

Android 13 wprowadził budowanie jąder za pomocą Bazel (Kleaf), zastępując build.sh .

Aby zbudować moduły virtual_device , uruchom:

tools/bazel build //common-modules:virtual_device_x86_64_dist

Aby utworzyć dystrybucję, uruchom:

tools/bazel run //common-modules:virtual_device_x86_64_dist -- --dist_dir=$DIST_DIR

Więcej szczegółów na temat budowania jądra Kleafa za pomocą Bazel - można znaleźć w dokumentacji AOSP .

Uruchamianie jądra

Istnieje wiele sposobów na uruchomienie jądra zbudowanego na zamówienie. Poniżej przedstawiono znane sposoby odpowiednie dla różnych scenariuszy rozwoju.

Osadzanie w kompilacji obrazu Androida

Skopiuj Image.lz4-dtb do odpowiedniej lokalizacji binarnej jądra w drzewie AOSP i odbuduj obraz rozruchowy.

Alternatywnie, zdefiniuj zmienną TARGET_PREBUILT_KERNEL podczas używania make bootimage (lub dowolnego innego wiersza poleceń make , który buduje obraz rozruchowy). Ta zmienna jest obsługiwana przez wszystkie urządzenia, ponieważ jest konfigurowana przez device/common/populate-new-device.sh . Na przykład:

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

Flashowanie i uruchamianie jąder za pomocą fastboot

Najnowsze urządzenia mają rozszerzenie bootloader, aby usprawnić proces generowania i uruchamiania obrazu rozruchowego.

Aby uruchomić jądro bez flashowania:

adb reboot bootloader
fastboot boot Image.lz4-dtb

Używając tej metody, jądro nie jest w rzeczywistości flashowane i nie będzie zachowywać się po ponownym uruchomieniu.

Dostosowywanie kompilacji jądra

Na proces kompilacji i wynik mogą mieć wpływ zmienne środowiskowe. Większość z nich jest opcjonalna i każda gałąź jądra powinna mieć odpowiednią domyślną konfigurację. Poniżej wymieniono najczęściej używane. Aby uzyskać pełną (i aktualną) listę, zapoznaj się z build/build.sh .

Zmienna środowiskowa Opis Przykład
BUILD_CONFIG Zbuduj plik konfiguracyjny, z którego zainicjujesz środowisko kompilacji. Lokalizacja musi być zdefiniowana względem katalogu głównego repozytorium. Domyślnie build.config .
Obowiązkowe dla zwykłych jąder.
BUILD_CONFIG=common/build.config.gki.aarch64
CC Zastąp kompilator, który ma być używany. Wraca do domyślnego kompilatora zdefiniowanego przez build.config . CC=clang
DIST_DIR Podstawowy katalog wyjściowy dla dystrybucji jądra. DIST_DIR=/path/to/my/dist
OUT_DIR Podstawowy katalog wyjściowy dla kompilacji jądra. OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG Pomiń make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER Pomiń make mrproper SKIP_MRPROPER=1

Niestandardowa konfiguracja jądra dla lokalnych kompilacji

Jeśli potrzebujesz regularnie przełączać opcję konfiguracji jądra, na przykład podczas pracy nad funkcją, lub jeśli potrzebujesz ustawić opcję do celów programistycznych, możesz osiągnąć tę elastyczność, zachowując lokalną modyfikację lub kopię konfiguracji kompilacji.

Ustaw zmienną POST_DEFCONFIG_CMDS na instrukcję, która jest oceniana zaraz po wykonaniu zwykłego kroku make defconfig . Ponieważ pliki build.config są pozyskiwane w środowisku kompilacji, funkcje zdefiniowane w build.config mogą być wywoływane jako część poleceń post-defconfig.

Typowym przykładem jest wyłączenie optymalizacji czasu łącza (LTO) dla jądra z kreskowaniem podczas tworzenia. Chociaż LTO jest korzystne dla wydanych jąder, obciążenie w czasie kompilacji może być znaczne. Poniższy fragment kodu dodany do lokalnego build.config powoduje trwałe wyłączenie LTO podczas korzystania z build/build.sh .

POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
    ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
         -d LTO \
         -d LTO_CLANG \
         -d CFI \
         -d CFI_PERMISSIVE \
         -d CFI_CLANG
    (cd ${OUT_DIR} && \
     make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
}

Identyfikacja wersji jądra

Możesz zidentyfikować poprawną wersję do kompilacji z dwóch źródeł: drzewa AOSP i obrazu systemu.

Wersja jądra z drzewa AOSP

Drzewo AOSP zawiera wstępnie zbudowane wersje jądra. Dziennik git ujawnia poprawną wersję jako część komunikatu zatwierdzenia:

cd $AOSP/device/VENDOR/NAME
git log --max-count=1

Jeśli wersja jądra nie jest wymieniona w dzienniku git, pobierz ją z obrazu systemu, jak opisano poniżej.

Wersja jądra z obrazu systemu

Aby określić wersję jądra używaną w obrazie systemu, uruchom następujące polecenie w pliku jądra:

file kernel

W przypadku plików Image.lz4-dtb uruchom:

grep -a 'Linux version' Image.lz4-dtb

Tworzenie obrazu rozruchowego

Możliwe jest zbudowanie obrazu rozruchowego przy użyciu środowiska budowania jądra. Aby to zrobić, potrzebujesz binarnego ramdysku, który możesz uzyskać, pobierając obraz rozruchowy GKI i rozpakowując go. Dowolny obraz rozruchowy GKI z powiązanej wersji Androida będzie działał.

tools/mkbootimg/unpack_bootimg.py --boot_img=boot-5.4-gz.img
mv $KERNEL_ROOT/out/ramdisk gki-ramdisk.lz4

Folder docelowy to katalog najwyższego poziomu drzewa jądra (bieżący katalog roboczy).

Jeśli programujesz z masterem AOSP, możesz zamiast tego pobrać artefakt kompilacji ramdisk-recovery.img z kompilacji aosp_arm64 na ci.android.com i użyć go jako pliku binarnego ramdysku.

Jeśli masz plik binarny z ramdyskiem i skopiujesz go do gki-ramdisk.lz4 w katalogu głównym kompilacji jądra, możesz wygenerować obraz rozruchowy, wykonując:

BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=Image GKI_RAMDISK_PREBUILT_BINARY=gki-ramdisk.lz4 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh

Jeśli pracujesz z architekturą opartą na x86, zastąp Image bzImage , a aarch64 x86_64 :

BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=bzImage GKI_RAMDISK_PREBUILT_BINARY=gki-ramdisk.lz4 BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh

Ten plik znajduje się w katalogu artefaktów $KERNEL_ROOT/out/$KERNEL_VERSION/dist .

Obraz rozruchowy znajduje się w out/<kernel branch>/dist/boot.img .