Na tej stronie szczegółowo opisano proces tworzenia niestandardowych jąder dla urządzeń z systemem Android. Te instrukcje poprowadzą Cię przez proces wybierania właściwych źródeł, budowania jądra i osadzania wyników w obrazie systemu zbudowanym na podstawie projektu Android Open Source Project (AOSP).
Możesz uzyskać nowsze źródła jądra, korzystając z Repo ; zbuduj je bez dalszej konfiguracji, uruchamiając build/build.sh
z katalogu głównego kasy źródłowej.
Pobieranie źródeł i narzędzi do tworzenia
W przypadku najnowszych jąder użyj repo
, aby pobrać źródła, zestaw narzędzi i skrypty kompilacji. Niektóre jądra (na przykład jądra Pixela 3) wymagają źródeł z wielu repozytoriów Git, podczas gdy inne (na przykład zwykłe jądra) wymagają tylko jednego źródła. Korzystanie z metody 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 wspólnych jąder systemu Android i płytek programistycznych dostępnych za pomocą tej metody. Szczegółowe informacje na temat pobierania i kompilowania jąder dla urządzeń Pixel można znaleźć w sekcji Tworzenie jądra Pixel .
Urządzenie | Ścieżka binarna w drzewie AOSP | Oddziały repo |
---|---|---|
Hikey960 | urządzenie/linaro/jądro-hikey | wycieczka-linaro-android-4.14 wycieczka-linaro-android-4.19 wspólny-Android12-5.4 wspólny-Android13-5.10 |
Beagle x15 | urządzenie/ti/beagle_x15-kernel | omap-beagle-x15-android-4.14 omap-beagle-x15-android-4.19 |
Wspólne jądro Androida | 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-Android14-5.15 wspólny-Android14-6.1 wspólna linia główna Androida |
Budowa jądra
Budowanie z Bazelem (Kleafem)
W Androidzie 13 wprowadzono budowanie jąder za pomocą Bazela .
Aby zbudować jądro GKI dla architektury aarch64, sprawdź gałąź Android Common Kernel nie wcześniejszą niż Android 13, a następnie uruchom następującą komendę:
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ślona, zobacz dane wyjściowe polecenia, aby poznać lokalizację artefaktów. Szczegółowe informacje można znaleźć w dokumentacji AOSP .
Budowanie za pomocą build.sh (starsza wersja)
W przypadku oddziałów z systemem Android 12 lub starszym LUB oddziałów bez Kleafa:
build/build.sh
Plik binarny jądra, moduły i odpowiadający im obraz znajdują się w katalogu out/ BRANCH /dist
.
Tworzenie modułów dostawcy dla urządzenia wirtualnego
W Androidzie 13 wprowadzono budowanie jąder za pomocą Bazela (Kleaf), zastępując build.sh
.
Aby zbudować moduły virtual_device
, uruchom:
tools/bazel build //common-modules/virtual-device:virtual_device_x86_64_dist
Aby utworzyć dystrybucję, uruchom:
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist -- --dist_dir=$DIST_DIR
Więcej szczegółów na temat budowania jądra Androida za pomocą Bazela znajdziesz w artykule. Kleaf — Budowanie jądra Androida za pomocą Bazela .
Aby uzyskać szczegółowe informacje na temat obsługi Kleafa dla poszczególnych architektur, zobacz Wsparcie Kleafa dla urządzeń i jąder .
Tworzenie modułów dostawcy dla urządzenia wirtualnego za pomocą build.sh (starsza wersja)
W Androidzie 12 Mątwy i Złota Rybka 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
W systemie Android 11 wprowadzono GKI , które dzieli jądro na obraz jądra utrzymywany przez Google i moduły obsługiwane przez dostawcę, które są budowane osobno.
Ten przykład pokazuje konfigurację obrazu jądra:
BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh
Poniższy przykład pokazuje konfigurację modułu (mątwa i emulator):
BUILD_CONFIG=common-modules/virtual-device/build.config.cuttlefish.x86_64 build/build.sh
Obsługa Kleaf dla urządzeń i jąder
W poniższej tabeli wymieniono obsługę Kleafa dla poszczególnych jąder urządzeń. W przypadku urządzeń niewymienionych na liście należy skontaktować się z producentem urządzenia.
Urządzenie | Oddziały repo | Wsparcie Kleafa | wsparcie build/build.sh |
---|---|---|---|
Wspólne jądro Androida db845c Urządzenie wirtualne (x86_64, arm64) Urządzenie wirtualne (i686, ramię) Rockpi4 | 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ólne jądro Androida | wspólny-Android13-5.10 wspólny-Android13-5.15 | ✅ | ✅ (oficjalne) 1 |
Wspólne jądro Androida | wspólny-Android14-5.15 wspólny-Android14-6.1 wspólny-Android15-6.1 wspólna linia główna Androida | ✅ | ❌ |
db845c | wspólny-Android13-5.10 | ❌ | ✅ |
db845c | wspólny-Android13-5.15 | ✅ | ✅ (oficjalne) 1 |
db845c | wspólny-Android14-5.15 wspólny-Android14-6.1 wspólny-Android15-6.1 wspólna linia główna Androida | ✅ | ❌ |
Urządzenie wirtualne (x86_64, arm64) | wspólny-Android13-5.10 wspólny-Android13-5.15 | ✅ (oficjalne) 1 | ⚠️ (niekonserwowany) 2 |
Urządzenie wirtualne (x86_64, arm64) | wspólny-Android14-5.15 wspólny-Android14-6.1 wspólny-Android15-6.1 wspólna linia główna Androida | ✅ | ❌ |
Urządzenie wirtualne (i686, ramię) | wspólny-Android13-5.10 wspólny-Android13-5.15 | ❌ | ✅ |
Urządzenie wirtualne (i686, ramię) | wspólny-Android14-5.15 wspólny-Android14-6.1 wspólny-Android15-6.1 wspólna linia główna Androida | ✅ | ❌ |
Rockpi4 | wspólny-Android13-5.10 wspólny-Android13-5.15 | ❌ | ✅ |
Rockpi4 | wspólny-Android14-5.15 wspólny-Android14-6.1 wspólny-Android15-6.1 wspólna linia główna Androida | ✅ | ❌ |
Hikey960 | wycieczka-linaro-android-4.14 wycieczka-linaro-android-4.19 wspólny-Android12-5.4 wspólny-Android13-5.10 | ❌ | ✅ |
moduł fips140 | wspólny-Android12-5.10 wspólny-Android13-5.10 wspólny-Android13-5.15 | ❌ | ✅ |
moduł fips140 | wspólny-Android14-5.15 | ✅ | ❌ |
1 „Oficjalny” oznacza, że jest to oficjalny sposób budowania jądra, mimo że do budowania jądra można również zastosować alternatywny sposób. 2 „Nieobsługiwane” oznacza, że budowanie jądra za pomocą tej metody powinno działać, ale metoda kompilacji nie jest stale testowana. W przyszłości może przestać się budować. Zamiast tego użyj „oficjalnego” sposobu budowania. |
Uruchamianie jądra
Istnieje wiele sposobów uruchomienia niestandardowego jądra. Poniżej przedstawiono znane sposoby odpowiednie dla różnych scenariuszy rozwoju.
Osadzanie w kompilacji obrazu Androida
Skopiuj plik Image.lz4-dtb
do odpowiedniej lokalizacji binarnej jądra w drzewie AOSP i odbuduj obraz rozruchowy.
Alternatywnie zdefiniuj zmienną TARGET_PREBUILT_KERNEL
podczas korzystania z make bootimage
(lub dowolnego innego wiersza poleceń make
, który tworzy obraz startowy). Ta zmienna jest obsługiwana przez wszystkie urządzenia, ponieważ jest skonfigurowana w device/common/populate-new-device.sh
. Na przykład:
export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb
Flashowanie i uruchamianie jądra za pomocą fastboot
Najnowsze urządzenia mają rozszerzenie programu ładującego, które usprawnia proces generowania i uruchamiania obrazu rozruchowego.
Aby uruchomić jądro bez flashowania:
adb reboot bootloader
fastboot boot Image.lz4-dtb
Korzystając z tej metody, jądro w rzeczywistości nie jest flashowane i nie będzie zachowywane po ponownym uruchomieniu.
Uruchamianie jądra na mątwie
Możesz uruchamiać jądra w wybranej architekturze na urządzeniach mątwy .
Aby uruchomić urządzenie mątwy z określonym zestawem artefaktów jądra , uruchom komendę cvd start
z docelowymi artefaktami jądra jako parametrami. Poniższe przykładowe polecenie wykorzystuje artefakty jądra dla celu arm64 z manifestu jądra common-android14-6.1
.
cvd start \
-kernel_path=/$PATH/$TO/common-android14-6.1/out/android14-6.1/dist/Image \
-initramfs_path=/$PATH/$TO/common-android14-6.1/out/android14-6.1/dist/initramfs.img
Aby uzyskać więcej informacji, zobacz Tworzenie jądra na mątwie .
Dostosowywanie kompilacji jądra
Aby dostosować kompilacje jądra do kompilacji Kleafa, zobacz dokumentację Kleafa .
Dostosowywanie kompilacji jądra za pomocą build.sh (starsza wersja)
W przypadku build/build.sh
na proces i wynik kompilacji mogą wpływać zmienne środowiskowe. Większość z nich jest opcjonalna i każda gałąź jądra powinna mieć odpowiednią domyślną konfigurację. Tutaj wymieniono najczęściej używane. Pełną (i aktualną) listę można znaleźć w build/build.sh
.
Zmienna środowiskowa | Opis | Przykład |
---|---|---|
BUILD_CONFIG | Kompiluj plik konfiguracyjny, z którego inicjujesz środowisko kompilacji. Lokalizacja musi być zdefiniowana względem katalogu głównego Repo. Domyślnie jest to build.config .Obowiązkowe dla popularnych 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 kompilacji lokalnych
W Androidzie 14 i nowszych możesz używać fragmentów defconfig do dostosowywania konfiguracji jądra. zobacz dokumentację Kleafa na temat fragmentów defconfig .
Niestandardowa konfiguracja jądra dla kompilacji lokalnych z konfiguracjami kompilacji (starsza wersja)
W systemie Android 13 i starszych zobacz poniższe informacje.
Jeśli musisz regularnie zmieniać opcję konfiguracji jądra, na przykład podczas pracy nad funkcją, lub jeśli potrzebujesz opcji do ustawienia w celach programistycznych, możesz osiągnąć tę elastyczność, zachowując lokalną modyfikację lub kopię konfiguracji kompilacji.
Ustaw zmienną POST_DEFCONFIG_CMDS na instrukcję, która będzie oceniana zaraz po wykonaniu zwykłego kroku make defconfig
. Ponieważ pliki build.config
są pobierane ze środowiska kompilacji, funkcje zdefiniowane w build.config
można wywoływać w ramach poleceń post-defconfig.
Typowym przykładem jest wyłączenie optymalizacji czasu łącza (LTO) dla jąder crosshatch podczas programowania. Chociaż LTO jest korzystne dla wydanych jąder, obciążenie w czasie kompilacji może być znaczące. Poniższy fragment dodany do lokalnego build.config
trwale wyłącza 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
Właściwą wersję do zbudowania można zidentyfikować na podstawie dwóch źródeł: drzewa AOSP i obrazu systemu.
Wersja jądra z drzewa AOSP
Drzewo AOSP zawiera prekompilowane 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, uzyskaj 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ącą komendę w stosunku do 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 kompilacji jądra.
Tworzenie obrazu rozruchowego dla urządzeń za pomocą init_boot
W przypadku urządzeń z partycją init_boot
obraz rozruchowy jest budowany wraz z jądrem. Obraz initramfs
nie jest osadzony w obrazie startowym.
Na przykład za pomocą Kleafa możesz zbudować obraz rozruchowy GKI za pomocą:
tools/bazel run //common:kernel_aarch64_dist -- --dist_dir=$DIST_DIR
Za pomocą build/build.sh
(legacy) możesz zbudować obraz rozruchowy GKI za pomocą:
BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
Obraz rozruchowy GKI znajduje się w $DIST_DIR .
Tworzenie obrazu rozruchowego dla urządzeń bez init_boot
(starsza wersja)
W przypadku urządzeń bez partycji init_boot
potrzebny jest plik binarny ramdysku, który można uzyskać, pobierając obraz rozruchowy GKI i rozpakowując go. Każdy 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 przy użyciu głównego 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.
Kiedy masz plik binarny ramdysku i skopiowałeś 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, zamień Image
na bzImage
i aarch64
na 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
Plik ten znajduje się w katalogu artefaktów $KERNEL_ROOT/out/$KERNEL_VERSION/dist
.
Obraz rozruchowy znajduje się w out/<kernel branch>/dist/boot.img
.