高通GKI内核开发说明(6115A14为例)
1、defconfig
bengal_consolidate.config、consolidate.fragment、bengal_GKI.config、gki_defconfig、bengal-consolidate_defconfig、bengal-gki_defconfig、.config等kernel defconfig配置文件的生成关系整理。
userdebug版本kernel defconfig生成逻辑
bengal_consolidate.config
| 覆盖
V
consolidate.fragment
| 覆盖
V
bengal_GKI.config
| 覆盖
V
gki_defconfig
| 生成
V
bengal-consolidate_defconfig
| 生成
V
userdebug版本.config
user版本kernel defconfig生成逻辑
bengal_GKI.config
| 覆盖
V
gki_defconfig
| 生成
V
bengal-gki_defconfig
| 生成
V
user版本.config
各配置文件的作用:
| 文件 | 说明 |
|---|---|
| bengal_consolidate.config | 厂商调试配置。该配置文件仅影响userdebug版本,并且优先级最高,在此处添加的配置会覆盖以下所有文件。 |
| consolidate.fragment | 谷歌调试配置。不能随意修改。该配置文件仅影响userdebug版本,由于厂商的调试配置文件优先级高于谷歌调试配置,因此修改此文件的作用不大,如果需要增加调试配置可用直接加到厂商调试配置文件中。 |
| bengal_GKI.config | 仅包含厂商必须的、符合 GKI 规范的修改,一般用于增加内核模块驱动。此文件修改会影响user和userdebug版本,系统通常会运行 check_defconfig。如果 bengal_GKI.config 里的内容和 gki_defconfig 产生了冲突(比如 Google 要求 CONFIG_XX=y,你改成了 CONFIG_XX=n),编译就会报错。 |
| gki_defconfig | 谷歌基本配置,不能随意修改,否则编译出来的KERNEL无法通过VTS测试 |
2、module
kernel 生成目录与kernel module关系说明
| 目录 | 说明 |
|---|---|
| TARGET/kernel_platform/out/msm-kernel-bengal-consolidate/gki_kernel | 带调试特性的内核 |
| TARGET/kernel_platform/out/msm-kernel-bengal-consolidate/msm-kernel | 在调试环境下编译出的驱动模块 |
| TARGET/kernel_platform/out/msm-kernel-bengal-gki/gki_kernel | GKI标准内核 |
| TARGET/kernel_platform/out/msm-kernel-bengal-gki/msm-kernel | 标准环境下编译出的厂商驱动模块 |
修改bengal_GKI.config生成的kernel module都会被打包到vendor RAMSIDK,该分区被打包进了vendor_boot.img。
所有生成的kernel module都会临时放到TARGET/device/qcom/bengal-kernel,该目录下存在三个modules.load,下面表格将解释其作用
| 文件 | 对应分区 | 启动阶段 | 核心任务 |
|---|---|---|---|
./modules.load(根目录) |
vendor_boot | 第一阶段 init (First Stage Init) | 存放启动必须的驱动(如存储 UFS、显存管理、分段内存管理等)。如果这里漏了驱动,手机会卡在 bootloader 或无限重启。 |
| ./system_dlkm/modules.load | system_dlkm | 第二阶段 init (Second Stage) | 存放与 GKI 内核版本高度绑定的“核心”模块。这个路径带版本号,是为了确保内核与模块完全匹配(ABI 一致)。 |
| ./vendor_dlkm/modules.load | vendor_dlkm | 第二阶段 init | 存放厂商特有的外设驱动(如 Wi-Fi、音频、传感器、GPU 驱动等)。 |
3、device tree
dtb-base和dtb-overlay目录关系说明
| 目录 | 说明 |
|---|---|
| TARGET/kernel_platform/qcom/proprietary/devicetree/qcom/ | 主设备树和设备树覆盖文件所在目录 |
| TARGET/vendor/qcom/proprietary/audio-devicetree | 音频部分厂商设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/bt-devicetree | 蓝牙设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/camera-devicetree | 摄像头设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/data-devicetree | IPA备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/display-devicetree | 屏幕与触摸设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/eSE-devicetree | 嵌入式安全单元设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/graphics-devicetree | 显卡设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/mmrm-devicetree | Multimedia Resource Manager(多媒体资源管理器)设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/nfc-device | NFC设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/simcom-devicetree | 芯讯通定义的设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/video-devicetree | 视频编码设备树覆盖文件 |
| TARGET/vendor/qcom/proprietary/wlan-devicetree | WiFi设备树覆盖文件 |
编译工具链会通过设备树的msm-id、board-id、pmic-id将vendor部分的dtb-overlay与主的dtb-overlay合并。
注意事项:
因为dtb-overlay最终是由多个单独的dtbo合并,因此有以下规则需要遵循: 1、某个dtb-overlay中定义的节点不能被另外一个dtb-overlay引用。如camera-devicetree中定义的节点不能被display-devicetree引用。
2、如果一个节点需要被多个dtb-overlay引用,那么这个节点必须在dtb-base中定义。如camera-devicetree和display-devicetree中共用的部分regulator放在了qcom/scuba-regulator.dtsi,该文件包含在scuba-iot.dts的dtb-base中。
3、dtb-overlay中的不能使用设备树删除语法。
4、dtb-overlay中定义的节点仅能被当前dtb-overlay包含的dtsi文件引用。
如果报错“FDT_ERR_NOTFOUND” dtbo合并失败(不是dtbo编译报错),并非是找不到dtbo文件,而是上面1、2事项出现了问题,需要检查dtbo中引用的节点是否存在当前的dtb-overlay文件或与之匹配的dtb-base中。
Failed to apply 'xxxxx/camera-devicetree/scuba-camera.dtbo': FDT_ERR_NOTFOUND
Traceback (most recent call last):
File "xxxxx/TARGET/kernel_platform/build/android/merge_dtbs.py", line 504, in <module>
main()
... ...
returned non-zero exit status 1.
4、编译指令
常用单编指令,需要在TARGET目录执行
重编kernel和dtbo
生成的kernel module在kernel_platform/out/msm-kernel-bengal-consolidate/msm-kernel/drivers/
rm -rf device/qcom/bengal-kernel
rm -rf kernel_platform/out
rm -rf out/msm-kernel-*
cd kernel_platform
# BUILD_CONFIG=./msm-kernel/build.config.msm.bengal LTO=thin SKIP_MRPROPER=1 SKIP_DEFCONFIG=1 ./build/all-variants.sh "./build/build.sh"
# 改了defconfig用下面的这条指令,但是这样编译更全,速度会慢
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal LTO=thin ./build/all-variants.sh "./build/build.sh"
cd ..
cp --reflink -r kernel_platform/out .
source build/envsetup.sh
lunch bengal_515-userdebug
# userdebug版本
kernel_platform/build/android/prepare_vendor.sh bengal consolidate
# user版本
# kernel_platform/build/android/prepare_vendor.sh bengal
quick-build vendorramdisk
quick-build dtboimage
quick-build vendorbootimage
quick-build bootimage
重编kernel
rm -rf device/qcom/bengal-kernel/
rm -rf kernel_platform/out
rm -rf out/msm-kernel-*
cd kernel_platform
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal LTO=thin ./build/all-variants.sh "./build/build.sh"
cd ..
cp --reflink=auto -r kernel_platform/out .
重编dtbo
编译前需要注意要编译过一遍TARGET
source build/envsetup.sh
lunch bengal_515-userdebug
kernel_platform/build/android/prepare_vendor.sh bengal consolidate
quick-build dtboimage
编译abl
cd kernel_platform
bear ./build/build_abl.sh bengal
cd ..
cp kernel_platform/out/msm-kernel-bengal-consolidate/abl-userdebug/unsigned_abl.elf device/qcom/bengal-kernel/kernel-abl/abl-userdebug/
source build/envsetup.sh
lunch bengal_515-userdebug
quick-build aboot
5、刷写镜像
常用刷写镜像说明
vendor_boot.img包含dtb-base和vendor ramdisk(包含vendor kernel module和vendor init.rc)里面不带kernel image,而boot.img包含 GKI kernel image和generic ramdisk(包含generic kernel module)。
修改驱动模块不建议刷入vendor_boot.img,因为编译打包时间太长,推荐使用adb push到vendor_dlkm。
修改dtb-overlay建议刷入dtbo.img
修改dtb-base建议刷入vendor_boot.img。不是boot.img,原因上面已经提到。
6、自定义构建GKI内核
下载GKI的mainline kernel
mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b common-android14-5.15
repo sync
cd common
git checkout android13-5.15-2024-04_r1
实际执行的指令
# 需要python3环境
schroot -c jammy
# 国内需要设置代理才能访问
export http_proxy="172.21.4.128:7890"
export https_proxy="172.21.4.128:7890"
# 初始化repo
python3 /usr/bin/repo init -u https://android.googlesource.com/kernel/manifest -b common-android14-5.15
# 同步代码
python3 /usr/bin/repo sync
# 构建内核
tools/bazel run //common:kernel_aarch64_dist -- --destdir=./out
tools/bazel run --lto=thin //common:kernel_aarch64_dist -- --destdir=./out
下载预构建的内核
user版本预置内核(过GMS认证用)
修改BoardConfig.mk,并将Google分发的boot.img放如TARGET/device/qcom/bengal_515/目录
TARGET_NO_KERNEL := false
改成
# TARGET_NO_KERNEL := false ifneq ($(TARGET_BUILD_VARIANT),user) TARGET_NO_KERNEL := false else # Uses a prebuilt boot.img TARGET_NO_KERNEL := true BOARD_PREBUILT_BOOTIMAGE := device/qcom/bengal_515/boot.img endif
7、GKI认证时可能遇到的问题
1、需要调用的函数不在ABI接口列表
如果被调用的函数不在ABI接口列表,但是这个函数内所调用的其它函数在ABI接口列表。此时可以自行重新实现一个功能相同的函数,并改名(防止符号表重名),最后直接调用这个改名的函数。
参考:6115_2290_A14_SPF10_AP/TARGET/kernel_platform/msm-kernel/drivers/extcon/extcon-usbc-tusb320.c
static int typec_get_fw_cap_v2(struct typec_capability *cap,
struct fwnode_handle *fwnode)
{
const char *cap_str;
int ret;
cap->fwnode = fwnode;
ret = fwnode_property_read_string(fwnode, "power-role", &cap_str);
if (ret < 0)
return ret;
ret = typec_find_port_power_role(cap_str);
if (ret < 0)
return ret;
cap->type = ret;
/* USB data support is optional */
ret = fwnode_property_read_string(fwnode, "data-role", &cap_str);
if (ret == 0) {
ret = typec_find_port_data_role(cap_str);
if (ret < 0)
return ret;
cap->data = ret;
}
/* Get the preferred power role for a DRP */
if (cap->type == TYPEC_PORT_DRP) {
cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
ret = fwnode_property_read_string(fwnode, "try-power-role", &cap_str);
if (ret == 0) {
ret = typec_find_power_role(cap_str);
if (ret < 0)
return ret;
cap->prefer_role = ret;
}
}
return 0;
}
2、进入Recovery后某个kernel module导致死机
如果这个内核模块不是那么重要,不加载也不会造成功能受限,那么可以在Recovery屏蔽指定内核模块。
6115_2290_A14_SPF10_AP/TARGET/vendor/qcom/proprietary/kernel-scripts/kernel-platform/kernel-platform-board.mk
BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD := $(filter-out $(KERNEL_PREBUILT_DIR)/vendor_dlkm/snd-usb-audio-qmi.ko,$(BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD))
3、升级boot导致kernel接口变更,造成死机
只能修改对应驱动代码,使用驱动保留的KABI接口

浙公网安备 33010602011771号