本文将从设备树的编译与分区、运行这2个部分来介绍设备树的匹配流程。
一、编译与分区
DTS(DeviceTree Source)就是我们经常修改的*.dts和*.dtsi文件。DTS的规范可以参照https://www.devicetree.org/specifications/
DTB(DeviceTree Blob)是由DTS编译生成的二进制文件
DTC(DeviceTreeCompiler)用来将DTS编译成DTB的工具
指定DTC_EXT变量,DTC就是外部指定的二进制,没指定就是obj/KERNEL_OBJ/scripts/dtc/dtc,有些平台DTC_EXT就定义的out/host/linux-x86/bin/dtc
1)Android 8之前
Android 8之前没有区分,平台相关的DTS与ODM/OEM相关的DTS都放在一个DTS,编译产物dtb.img一般是打包至boot.img。
如果需要兼容多种硬件,会编译多个*.dtb,然后在bootloader区分硬件来加载匹配的dtb
Android 8之后为了更好的解耦与升级,google引入了DTO,将DTS分成两部分,一部分是平台相关的DTS,仍是编译成dtb.img打包至boot.img,一部分是ODM/OEM根据硬件客制化修改的DTS,编译的产物放到dtbo分区
Kernel-5.4以上由于GKI问题,dtb.img不再打包到boot.img,而是放入vendor_boot.img,加入vendor_boot分区,需要BOARD_BOOT_HEADER_VERSION等于3,bootloader加载也会使用到这个值
如果dts中需要用config来区分的,可以导入这个头文件 <generated/autoconf.h>,如果需要用外部宏定义来区分的,可以根据宏在dtc_cpp_flag添加-DXXX来新增宏让DTS来使用
而DTC_FLAG变量是给dtc用的,如果有需要可以针对单个dtb来使能
比如obj-y += a.dtb,可以在对应的makefile DTC_FLAG_a来给dtc传参
可以在out下面dtb的位置找到隐藏文件里面有保存命令
比如a.dtb,就可以查看.a.dtb.cmd文件
不同vendor指定dtb的方式不同,就介绍下android8之后两个vendor dtb的指定,进行技术参考。
dtbo-y+=board1.dtbo
board1.dtbo-base := soc.dtb
dtbo-y+=board2.dtbo
board2.dtbo-base := soc.dtb
新增了一个makefile scripts/Makefile.dtbo
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
CONFIG_BUILD_ARM64_DTB_OVERLAY_IMAGE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES="soc"
CONFIG_BUILD_ARM64_DTB_OVERLAY_IMAGE_NAMES="board1board2”
使用CDT(Configuration data table),config_data_table数组会定义platform_id和platform subtype可以用来区分不同的硬件设计,数组会编译到xbl.elf,也可以单独生成一个镜像cdt.bin,不同项目生成不同的cdt.bin,刷机上就可以区分开不同的dts
boot_images\qcompkg\xblloader\Boot_config_flash.c
boot_update_config_data_table()会判断用cdt.bin的数据还是xbl.elf的数据,platform_id和platform subtype,还有CPU/PMIC信息会通过共享内存传递至ABL
bootable/bootloader/edk2/QcomModulePkg/Library/BootLib/BootLinux.c
DTBImgCheckAndAppendDT()
这里就是上面提到的HEADER VERSION等于3会从vendor_boot后去获取dtb.img
bootable/bootloader/edk2/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
读取soc dtb中qcom,msm-id;qcom,board-id;qcom,pmic-id这三个属性,从多个soc dtb中选取一个最匹配的加载到内存中
之后读取board dtbo中qcom,msm-id;qcom,board-id;qcom,pmic-id这三个属性还有DDR等信息,从多个board dtbo中选取一组匹配的加载到内存中,可以将board相关的dts拆分成多个,比如board1/board2给项目A使用,board1/board3给项目B使用
然后使用ufdt_apply_multi_overlay()将找到soc dtb和多组board dtb合并到一个地址,然后把这个地址通过R2寄存器传递给kernel
Vendor2与vendor1类似,只是vendor2在lk通过GPIO或者其他信息选择一个board dtbo
rsc_get_dtbo_index()中的rsc是Run-time Switchable Configuration机制,运行时动态切换的。
Vendor2需要自己实现customized_get_odm_mdtbo_index()来选择不同的dtbo,下标和kernel中CONFIG_BUILD_ARM64_DTB_OVERLAY_IMAGE_NAMES定义的内容对应
https://source.android.google.cn/devices/architecture/dto
Copyright© 2013-2019