Android 设备树的匹配流程

4340次阅读  |  发布于2年以前

本文将从设备树的编译与分区、运行这2个部分来介绍设备树的匹配流程。

一、编译与分区

1. 名词介绍

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

2. DTS**与分区的变化**

1)Android 8之前

Android 8之前没有区分,平台相关的DTS与ODM/OEM相关的DTS都放在一个DTS,编译产物dtb.img一般是打包至boot.img。

如果需要兼容多种硬件,会编译多个*.dtb,然后在bootloader区分硬件来加载匹配的dtb

2) Android 8**之后**

Android 8之后为了更好的解耦与升级,google引入了DTO,将DTS分成两部分,一部分是平台相关的DTS,仍是编译成dtb.img打包至boot.img,一部分是ODM/OEM根据硬件客制化修改的DTS,编译的产物放到dtbo分区

3) Android 11**以上+kernel-5.4以上**

Kernel-5.4以上由于GKI问题,dtb.img不再打包到boot.img,而是放入vendor_boot.img,加入vendor_boot分区,需要BOARD_BOOT_HEADER_VERSION等于3,bootloader加载也会使用到这个值

3. DTB**的生成**

如果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的指定,进行技术参考。

1) vendor1**指定dtb**

dtbo-y+=board1.dtbo

board1.dtbo-base := soc.dtb

dtbo-y+=board2.dtbo

board2.dtbo-base := soc.dtb

新增了一个makefile scripts/Makefile.dtbo

2) vendor2**指定dtb**

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”

二、运行

1. vendor1

(1) XBL

使用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

(2) 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

2. vendor2

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

京ICP备2023019179号-2