3. 源码目录结构解析
拿到一份高通Android BSP源码后,第一件事不是急着编译,而是先看清目录结构。因为BSP的构建系统本质上是一套“路径驱动”的机制:编译脚本、BoardConfig、Android.mk/Android.bp、设备树、内核配置,全部通过相对路径互相引用。路径认错,后面所有配置都会连锁出错。本节把源码树拆成三条主线来看:AOSP公共源码树、高通专有目录、以及bootloader与kernel目录。
一、顶层目录:AOSP公共源码树
解压后的源码根目录通常包含以下关键目录,它们由AOSP定义,高通在其上做增量扩展:
build/:AOSP构建系统核心,包含make/core、make/target、soong/等。BoardConfig.mk的解析规则、PRODUCT_*变量的展开逻辑都在这里。frameworks/:Java框架层,frameworks/base是系统服务与核心API所在,frameworks/av负责音视频,frameworks/native是Native服务与Binder。system/:底层系统组件,如system/core(init、logd、adb)、system/sepolicy(SELinux策略)。hardware/:HAL接口定义,hardware/interfaces是HIDL/AIDL接口的规范目录,hardware/libhardware是传统HAL。packages/:系统应用与输入法、设置等,packages/apps/Settings是常见定制入口。external/:第三方开源库,如external/skia、external/libcxx。out/:编译输出目录,out/target/product/<device>/下生成镜像与中间产物。
这些目录是“平台无关”的,理解它们的作用有助于判断某个改动应该落在AOSP层还是高通层。例如修改默认语言应改build/target/product下的产品定义,而修改某个SoC的GPIO初始化则应落到高通专有目录。
二、高通专有目录:vendor/qcom 与 device/qcom
高通BSP最核心的增量就在这两个目录,它们的分工非常明确:
device/qcom/ 存放“设备与产品配置”,是编译入口所在。典型结构如下:
device/qcom/
├── common/ # 所有高通平台共用的BoardConfig片段、init脚本
│ ├── BoardConfigCommon.mk
│ └── init/
├── <target>/ # 具体平台,如 kalama、pineapple
│ ├── BoardConfig.mk # 板级配置:分区、内核、bootloader参数
│ ├── <target>.mk # 产品定义:PRODUCT_*变量
│ ├── AndroidBoard.mk # 板级构建规则
│ └── init.target.rc # 平台专属init
└── <device>/ # 具体机型,如某品牌旗舰
├── BoardConfig.mk
├── device.mk
└── overlay/ # 资源覆盖
其中BoardConfig.mk决定分区布局、内核路径、bootloader路径;<target>.mk决定打包哪些模块、哪些HAL、哪些应用。编译时通过lunch <target>-userdebug选择的就是这里的组合。
vendor/qcom/ 存放“高通私有实现”,通常以闭源或半开源形式提供:
vendor/qcom/proprietary/:高通私有库、固件、HAL实现,如display/、audio/、gps/、thermal/。vendor/qcom/opensource/:高通开源部分,如kernel相关脚本、commonsys。vendor/qcom/build/:高通构建辅助脚本。
需要特别注意:vendor/qcom/proprietary中的内容往往与SoC型号强绑定,换平台时不能直接复用。而device/qcom/common中的BoardConfig片段则具有较好的跨平台复用性。
三、bootloader与kernel目录
高通平台的bootloader通常称为ABL(Application Bootloader),源码位于bootable/bootloader/edk2/或高通提供的bootloader/目录下。其结构大致为:
bootable/bootloader/edk2/
├── QcomPkg/ # 高通平台包
│ ├── Library/ # 驱动库
│ ├── Include/ # 头文件
│ └── Settings/ # 平台配置
├── ArmPkg/ # ARM架构支持
├── MdePkg/ # EDK2基础包
└── UefiCpuPkg/ # CPU相关
ABL负责初始化DDR、加载并校验boot镜像、实现fastboot协议。修改启动logo、fastboot命令、分区表通常在这里。
kernel目录则位于kernel/msm-<version>/或kernel/<platform>/,典型结构:
kernel/msm-5.15/
├── arch/arm64/boot/dts/vendor/qcom/ # 设备树
├── arch/arm64/configs/ # defconfig
├── drivers/ # 驱动
├── include/ # 头文件
└── scripts/ # 构建脚本
设备树是BSP定制的重点,arch/arm64/boot/dts/vendor/qcom/下按平台和机型组织,如kalama.dtsi、pineapple.dtsi。defconfig决定内核编译选项,通常命名为<platform>_defconfig。
grep -r "关键字" device/qcom/ vendor/qcom/快速定位。若在device/qcom找到,说明是产品级配置;若在vendor/qcom/proprietary找到,说明是高通私有实现,修改需谨慎。
四、三条主线的协作关系
把上述内容串起来看:AOSP提供通用框架与构建系统,device/qcom提供产品与板级配置,vendor/qcom提供SoC私有实现,bootloader负责启动链前半段,kernel负责启动链后半段与硬件驱动。编译时,lunch选择device/qcom中的产品组合,构建系统据此拉取vendor/qcom的库、编译kernel、打包boot与system镜像,最终生成可烧录的super.img、boot.img等。
理解这张图后,再去看具体的BoardConfig.mk,就能明白每一行变量为什么指向那个路径。例如TARGET_KERNEL_SOURCE := kernel/msm-5.15告诉构建系统去哪里找内核,TARGET_BOOTLOADER_BOARD_NAME := kalama告诉它用哪个bootloader配置。路径一旦对齐,后续的编译、烧录、调试才有稳定的基础。