第一个GKI 2.0的项目已经完结,做一些总结。
GKI 1.0 的时候,我们添加的设备驱动还是编译到boot.img中,在做XTS测试时刷google的boot.img.
GKI 2.0 在高通平台无论userdebug版本还是user版本boot.img都为google的boot.img,除了google的东西,任何第3方的驱动都以ko的形式存在。
1) qssi:
cd QSSI_DIR
source build/envsetup.sh
lunch qssi-userdebug
bash build.sh -j32 dist --qssi_only
========================
2) kernel:
cd VENDOR_DIR/
cd kernel_platform/msm-kernel/arch/arm64/boot/dts
ln -s ../../../../../qcom/proprietary/devicetree vendor
cd kernel_platform
按需要选择需要的配置编译:
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal VARIANT=consolidate BRANCH=msm-kernel-bengal-consolidate
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal VARIANT=gki BRANCH=msm-kernel-bengal-gki
========================
3) vendor:
cd VENDOR_DIR
mkdir out/
cp -r KERNEL_DIR/kernel_platform/out/* out
source build/envsetup.sh
lunch bengal_515-userdebug
./kernel_platform/build/android/prepare_vendor.sh bengal gki #选gki,或者consolidate
bash build.sh -j32 dist --target_only
=======================
4) generate super:
python QSSI_DIR/vendor/qcom/opensource/core-utils/build/build_image_standalone.py --image super --qssi_build_path --target_build_path --merged_build_path --target_lunch bengal_515 --output_ota
bootable目录:bootloader abl放置的目录,有些高通平台又把这个目录移出了kernel_platform
common目录: google GKI源码放置的目录, 编译出boot.img, 不可更改common中的代码,只能通过vendor hook的方式放钩子改变boot.img中的东西。
msm-kernel: 高通kernel源码放置的目录,包括高通的驱动和后面自己加的驱动都在这个目录,编译为ko
如果修改了驱动文件或者dts,使用下面的命令再次编译的话默认会清除之前编译的产生的中间文件,导致编译时间非常久,由于已经完整编译过增加 SKIP_MRPROPER=1 SKIP_DEFCONFIG=1
来节省编译时间。
cd kernel_platform
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal VARIANT=gki BRANCH=msm-kernel-bengal-gki ./build/build.sh
ramdisk: 查看 kernel_platform/msm-kernel/modules.list.msm.bengal 写在这里面的ko文件是编译到ramdisk里面的,ramdisk.img是合在vendor_boot.img中,修改这里面的驱动需要重新刷vendor_boot.img
vendor_dlkm: 其他的ko文件在vendor_dlkm分区,adb remount后push到/vendor_dlkm/lib/modules/下重启
cd kernel_platform
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal VARIANT=gki SKIP_MRPROPER=1 SKIP_DEFCONFIG=1 BRANCH=msm-kernel-bengal-gki ./build/build.sh
cd ..
rm -rf device/qcom/bengal-kernel/
source build/envsetup.sh
lunch bengal_515-userdebug
./kernel_platform/build/android/prepare_vendor.sh bengal gki ./kernel_platform/out/msm-kernel-bengal-gki
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-bengal_515.ninja vendorramdisk
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-bengal_515.ninja vendorbootimage
如果只是在vendor_dlkm的ko,只需要在第1步后到kernel_platform/out找到ko文件push进去就行了,不需要打包image.
dts源码分布有两部分一部分在kernel_platform下,这部分的remake命令
cd kernel_platform
BUILD_CONFIG=./msm-kernel/build.config.msm.bengal VARIANT=gki SKIP_MRPROPER=1 SKIP_DEFCONFIG=1 BRANCH=msm-kernel-bengal-gki ./build/build.sh
另外一部分在vendor/qcom/proprietary下,如 audio-devicetree bt-devicetree camera-devicetree data-devicetree display-devicetree graphics-devicetree 等
如果只修改了proprietary下的dts则只需要remake这部分dts,以下命令会编译proprietary下的dts,并和kernel_platform的dts进行merge
cd ..
rm -rf device/qcom/bengal-kernel/
source build/envsetup.sh
lunch bengal_515-userdebug
./kernel_platform/build/android/prepare_vendor.sh bengal gki ./kernel_platform/out/msm-kernel-bengal-gki
最后重新生成dtbo.img
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-bengal_515.ninja dtboimage
说明:dts编译出来的东西也分为2部分一个是dtb.img, 一个是dtbo.img 具体所修改的dts文件是编译到哪个需要看Makefile。 dtb.img是打包到vendor_boot.img的,我自己是先刷dtbo.img,不生效再刷vendor_boot.img。
cd kernel_platform/
./build/build_abl.sh bengal
cd ..
cp kernel_platform/out/msm-kernel-bengal-gki/abl-userdebug/unsigned_abl.elf device/qcom/bengal-kernel/kernel-abl/abl-userdebug/unsigned_abl.elf
./prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-bengal_515.ninja aboot
例如需要编译这个驱动CONFIG_TOUCHSCREEN_NT36XXX_I2C, 类似的audio kernel, display kernel也是使用build/build_module.sh编译
cd kernel_platform/
EXT_MODULES=../vendor/qcom/opensource/touch-drivers/ OUT_DIR=../out/target/product/bengal_515/obj/DLKM_OBJ/kernel_platform ./build/build_module.sh CONFIG_MSM_TOUCH=m CONFIG_TOUCHSCREEN_NT36XXX_I2C=y
既然是hook,那hook的点应该是某个trace point,可在include/trace/hooks/ 目录中.h文件中找到埋好的point。
// vendor hook point 的定义
logbuf.h
DECLARE_HOOK(android_vh_logbuf,
TP_PROTO(struct printk_ringbuffer *rb, struct printk_record *r),
TP_ARGS(rb, r))
kernel_platform/common/drivers/android/vendor_hooks.c
// 以printk为例,之前gki 1.0时如果用printk打印时想每条打印添加一些自己想要的
// 信息,直接修改printk.c, gki 2.0时 printk.c中埋了几个hook point
// 只能在hook point的地方切入。
// kernel_platform/common/kernel/printk/printk.c
// 以下是 vprintk_store 中埋的一个vendor hook,当跑到这时会调用
// 所有注册的vendor hook函数
int vprintk_store(int facility, int level,
const struct dev_printk_info *dev_info,
const char *fmt, va_list args)
{
...
trace_android_vh_logbuf(prb, &r);
...
}
// 如下是高通注册的printk.c中的vendor hook callback
// 由于高通已经注册了,我并未再写一个驱动注册 vendor hook callback
// 每条prink的 log产生时都有一个时间戳,但是这个时间休眠时是不走的
// 这里我给换成了基于boot的时间戳,即使休眠这个时间也会增加
kernel_platform/msm-kernel/drivers/soc/qcom/qcom_logbuf_boot_log.c
static void copy_boot_log(void *unused, struct printk_ringbuffer *prb,
struct printk_record *r)
{
...
+ // modify timestamp from CLOCK_MONOTONIC to CLOCK_BOOTTIME for printk
+ r->info->ts_nsec = ktime_get_boot_fast_ns();
...
}
int boot_log_register(struct device *dev)
{
int ret = 0;
ret = boot_log_init();
if (ret < 0)
return ret;
ret = register_trace_android_vh_logbuf(copy_boot_log, NULL);
if (ret) {
dev_err(dev, "Failed to register android_vh_logbuf hook\n");
kfree(boot_log_buf);
return ret;
}
ret = register_trace_android_vh_logbuf_pr_cont(copy_boot_log_pr_cont, NULL);
if (ret) {
dev_err(dev, "Failed to register android_vh_logbuf_pr_cont hook\n");
unregister_trace_android_vh_logbuf(copy_boot_log, NULL);
kfree(boot_log_buf);
}
return ret;
}
刚拿到一份SM6375的Android14基线的代码,kernel的编译又变了,好像是使用google的bazel编译,kernel的编译使用 build_with_bazel.py 这个东西,后续有接触这个东西再更新这部分内容。