Tạo nhân

Trang này trình bày chi tiết quy trình tạo kernel tuỳ chỉnh cho thiết bị Android. Các hướng dẫn này sẽ hướng dẫn bạn qua quy trình chọn nguồn phù hợp, tạo kernel và nhúng kết quả vào hình ảnh hệ thống được tạo từ Dự án nguồn mở Android (AOSP).

Tải nguồn và công cụ bản dựng xuống

Đối với các kernel gần đây, hãy sử dụng repo để tải các nguồn, chuỗi công cụ và tập lệnh bản dựng xuống. Một số kernel (ví dụ: kernel Pixel 3) yêu cầu nguồn từ nhiều kho lưu trữ git trong khi các kernel khác (ví dụ: kernel chung) chỉ yêu cầu một nguồn duy nhất. Việc sử dụng phương pháp repo đảm bảo thiết lập đúng thư mục nguồn.

Tải các nguồn cho nhánh thích hợp xuống:

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

Để xem danh sách các nhánh kho lưu trữ (BRANCH) có thể dùng với lệnh `repo init` trước đó, hãy xem Các nhánh kernel và hệ thống bản dựng của chúng.

Để biết thông tin chi tiết về cách tải và biên dịch kernel cho thiết bị Pixel, hãy xem bài viết Tạo kernel Pixel.

Tạo kernel

Tạo bằng Bazel (Kleaf)

Android 13 đã giới thiệu tính năng tạo kernel bằng Bazel.

Để tạo bản phân phối cho kernel GKI cho kiến trúc aarch64, hãy kiểm xuất một nhánh Kernel chung của Android không sớm hơn Android 13 và sau đó chạy lệnh sau:

tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]

Sau đó, tệp nhị phân kernel, các mô-đun và hình ảnh tương ứng sẽ nằm trong thư mục $DIST_DIR. Nếu bạn không chỉ định --destdir, hãy xem đầu ra của lệnh để biết vị trí của các cấu phần phần mềm. Để biết thông tin chi tiết, hãy tham khảo tài liệu về AOSP .

Tạo bằng build.sh (phiên bản cũ)

Đối với các nhánh ở Android 12 trở xuống HOẶC các nhánh không có Kleaf:

build/build.sh

Tệp nhị phân kernel, các mô-đun và hình ảnh tương ứng nằm trong thư mục out/BRANCH/dist

Tạo các mô-đun nhà cung cấp cho thiết bị ảo

Android 13 đã giới thiệu tính năng tạo kernel bằng Bazel (Kleaf), thay thế build.sh.

Để tạo bản phân phối cho các mô-đun của virtual_device, hãy chạy:

tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist [-- --destdir=$DIST_DIR]

Để biết thêm thông tin chi tiết về cách tạo kernel Android bằng Bazel, hãy xem. Kleaf – Tạo kernel Android bằng Bazel.

Để biết thông tin chi tiết về tính năng hỗ trợ Kleaf cho từng kiến trúc, hãy xem Tính năng hỗ trợ Kleaf cho thiết bị và kernel.

Tạo các mô-đun nhà cung cấp cho thiết bị ảo bằng build.sh (phiên bản cũ)

Trong Android 12, Cuttlefish và Goldfish hội tụ, vì vậy, chúng dùng chung một kernel: virtual_device. Để tạo các mô-đun của kernel đó, hãy sử dụng cấu hình bản dựng này:

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

Android 11 đã giới thiệu GKI, tách kernel thành một hình ảnh kernel do Google duy trì và các mô-đun do nhà cung cấp duy trì, được tạo riêng.

Ví dụ này cho thấy cấu hình hình ảnh kernel:

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

Ví dụ này cho thấy cấu hình mô-đun (Cuttlefish và Trình mô phỏng):

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

Chạy kernel

Có nhiều cách để chạy kernel được tạo tuỳ chỉnh. Sau đây là những cách đã biết phù hợp với nhiều tình huống phát triển.

Nhúng vào bản dựng hình ảnh Android

Sao chép Image.lz4-dtb vào vị trí tệp nhị phân kernel tương ứng trong cây AOSP và tạo lại hình ảnh khởi động.

Ngoài ra, hãy xác định biến TARGET_PREBUILT_KERNEL khi sử dụng make bootimage (hoặc bất kỳ make dòng lệnh nào khác tạo hình ảnh khởi động). Biến này được tất cả các thiết bị hỗ trợ vì được thiết lập thông qua device/common/populate-new-device.sh. Ví dụ:

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

Cài đặt ROM và khởi động nhân hệ điều hành bằng khởi động nhanh

Các thiết bị gần đây nhất có một tiện ích trình tải khởi động để đơn giản hoá quy trình tạo và khởi động hình ảnh khởi động.

Cách khởi động kernel mà không cần tải:

adb reboot bootloader
fastboot boot Image.lz4-dtb

Khi sử dụng phương thức này, kernel sẽ không thực sự được tải và sẽ không tồn tại sau khi khởi động lại.

Chạy kernel trên Cuttlefish

Bạn có thể chạy kernel trong kiến trúc mà bạn chọn trên các thiết bị Cuttlefish.

Để khởi động thiết bị Cuttlefish bằng một tập hợp cấu phần phần mềm kernel cụ thể, hãy chạy lệnh cvd create với các cấu phần phần mềm kernel mục tiêu làm tham số. Lệnh ví dụ sau đây sử dụng các cấu phần phần mềm kernel cho mục tiêu arm64 từ tệp kê khai kernel common-android14-6.1.

cvd create \
    -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

Để biết thêm thông tin, hãy xem bài viết Phát triển kernel trên Cuttlefish.

Tuỳ chỉnh bản dựng kernel

Để tuỳ chỉnh bản dựng kernel cho các bản dựng Kleaf, hãy xem tài liệu về Kleaf.

Tuỳ chỉnh bản dựng kernel bằng build.sh (phiên bản cũ)

Đối với build/build.sh, quy trình xây dựng và kết quả có thể bị ảnh hưởng bởi các biến môi trường. Hầu hết các biến này là không bắt buộc và mỗi nhánh kernel phải đi kèm với một cấu hình mặc định phù hợp. Các biến được sử dụng thường xuyên nhất được liệt kê ở đây. Để xem danh sách đầy đủ (và mới nhất) , hãy tham khảo build/build.sh.

Biến môi trường Mô tả Ví dụ
BUILD_CONFIG Tệp cấu hình bản dựng từ nơi bạn khởi chạy môi trường tạo bản dựng. Vị trí phải được xác định tương ứng với thư mục gốc của Kho lưu trữ directory. Giá trị mặc định là build.config.
Bắt buộc đối với các kernel chung.
BUILD_CONFIG=common/build.config.gki.aarch64
CC Ghi đè trình biên dịch sẽ được sử dụng. Sử dụng lại trình biên dịch mặc định được xác định bởi build.config. CC=clang
DIST_DIR Thư mục đầu ra cơ sở cho bản phân phối kernel. DIST_DIR=/path/to/my/dist
OUT_DIR Thư mục đầu ra cơ sở cho bản dựng kernel. OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG Bỏ qua make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER Bỏ qua make mrproper SKIP_MRPROPER=1

Cấu hình kernel tuỳ chỉnh cho các bản dựng cục bộ

Trong Android 14 trở lên, bạn có thể sử dụng các đoạn defconfig để tuỳ chỉnh cấu hình kernel. Hãy xem tài liệu về Kleaf về các đoạn defconfig.

Cấu hình kernel tuỳ chỉnh cho các bản dựng cục bộ bằng cấu hình bản dựng (phiên bản cũ)

Trong Android 13 trở xuống, hãy xem phần sau.

Nếu bạn cần chuyển đổi thường xuyên một tuỳ chọn cấu hình kernel, chẳng hạn như, khi làm việc trên một tính năng, hoặc nếu bạn cần đặt một tuỳ chọn cho mục đích phát triển, bạn có thể đạt được sự linh hoạt đó bằng cách duy trì một bản sao hoặc bản sửa đổi cục bộ của cấu hình bản dựng.

Đặt biến POST_DEFCONFIG_CMDS thành một câu lệnh được đánh giá ngay sau khi bước make defconfig thông thường hoàn tất. Vì các tệp build.config được lấy nguồn vào môi trường bản dựng nên các hàm được xác định trong build.config có thể được gọi như một phần của các lệnh sau defconfig.

Một ví dụ thường gặp là tắt tính năng tối ưu hoá thời gian liên kết (LTO) cho các kernel crosshatch trong quá trình phát triển. Mặc dù LTO có lợi cho các kernel đã phát hành, chi phí phát sinh tại thời gian xây dựng có thể đáng kể. Đoạn mã sau đây được thêm vào build.config cục bộ sẽ tắt LTO liên tục khi sử dụng 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)
}

Xác định phiên bản kernel

Bạn có thể xác định phiên bản chính xác để tạo bản dựng từ 2 nguồn: cây AOSP (Dự án nguồn mở Android) và hình ảnh hệ thống.

Phiên bản kernel từ cây AOSP

Cây AOSP chứa các phiên bản kernel được tạo sẵn. Nhật ký git cho thấy phiên bản chính xác như một phần của thông báo xác nhận:

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

Nếu phiên bản kernel không có trong nhật ký git, hãy lấy phiên bản đó từ hình ảnh hệ thống, như mô tả bên dưới.

Phiên bản kernel từ hình ảnh hệ thống

Để xác định phiên bản kernel được sử dụng trong hình ảnh hệ thống, hãy chạy lệnh sau đối với tệp kernel:

file kernel

Đối với các tệp Image.lz4-dtb, hãy chạy:

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

Tạo hình ảnh khởi động

Bạn có thể tạo hình ảnh khởi động bằng môi trường tạo bản dựng kernel.

Tạo hình ảnh khởi động cho các thiết bị có init_boot

Đối với các thiết bị có phân vùng init_boot, hình ảnh khởi động được tạo cùng với kernel. Hình ảnh initramfs không được nhúng vào hình ảnh khởi động.

Ví dụ: với Kleaf, bạn có thể tạo hình ảnh khởi động GKI bằng:

tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]

Với build/build.sh (phiên bản cũ), bạn có thể tạo hình ảnh khởi động GKI bằng:

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

Hình ảnh khởi động GKI nằm trong $DIST_DIR.

Tạo hình ảnh khởi động cho các thiết bị không có init_boot (phiên bản cũ)

Đối với các thiết bị không có phân vùng init_boot, bạn cần một tệp nhị phân ramdisk. Bạn có thể lấy tệp này bằng cách tải hình ảnh khởi động GKI xuống và giải nén. Mọi hình ảnh khởi động GKI từ bản phát hành Android được liên kết sẽ hoạt động.

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

Thư mục đích là thư mục cấp cao nhất của cây kernel (thư mục làm việc hiện tại ).

Nếu đang phát triển bằng nhánh phát hành AOSP mới nhất, bạn có thể tải cấu phần phần mềm bản dựng ramdisk-recovery.img xuống từ bản dựng aosp_arm64 trên ci.android.com và sử dụng cấu phần phần mềm đó làm tệp nhị phân ramdisk.

Khi bạn có tệp nhị phân ramdisk và đã sao chép tệp đó vào gki-ramdisk.lz4 trong thư mục gốc của bản dựng kernel, bạn có thể tạo hình ảnh khởi động bằng cách thực thi:

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

Nếu bạn đang làm việc với kiến trúc dựa trên x86, hãy thay thế Image bằng bzImage, và aarch64 bằng 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

Tệp đó nằm trong thư mục cấu phần phần mềm $KERNEL_ROOT/out/$KERNEL_VERSION/dist.

Hình ảnh khởi động nằm ở out/<kernel branch>/dist/boot.img.