Android dtbo(1) dto简介

发布时间 2023-05-04 20:17:53作者: yooooooo

设备树 (DT, Device Tree) 是用于描述 non-discoverable(google这样写的,意思应该就是硬件信息看不到) 硬件的命名节点和属性构成的一种数据结构。操作系统(例如在 Android 中使用的 Linux 内核)会使用 DT 来支持 Android 设备使用的各种硬件配置。硬件供应商会提供自己的 DT 源文件,接下来 Linux 会将这些文件编译成引导加载程序使用的DTB(Device Tree BLOB)文件。

设备树叠加层 (DTO,Device Tree Overlay) 可以使主要的dtb文件被overlay。使用 DTO 的引导加载程序可以维护系统芯片 (SoC) DT,并动态叠加针对特定设备的 DT,从而向树中添加节点并对现有树中的属性进行更改。
例如,像高通这种芯片厂商,针对某个soc,会在kernel中有个dts,描述了自己公版的硬件信息。把该soc卖给不同的手机厂商,如小米,oppo等,它们会在自己的device里再写个dts,也就是dtbo,做自己的个性化定制。自己的dtbo+高通的dtb形成系统中最终的设备树,这样方便厂商和芯片商维护各自的设备树。

本页详细介绍了引导加载程序加载 DT 的典型工作流程,并列出了常见的 DT 术语。

1、Android9的更新

在android9中,bootloader在将统一的dtb传递给kernel之前,不能修改dtbo中定义的属性。

1.1 加载设备树

在bootloader中使用设备树需要三个阶段,即构建、分区和运行,如下图所示:

1.构建

使用dtc将设备树*.dts文件编译为*.dtb文件
将dtb文件烧到开发板中bootloader可以访问的位置

2.分区

如需进行分区,请在bootloader可以访问的可信位置放置dtb文件,如下面所示,左边是将dtb与kernel一起放到boot分区,方法是将其附件到image.gz,并作为"kernel"传递给mkbootimg。右边是将dtb单独放在一个分区。

3.运行

将.dtb从存储(emmc)加载到内存(ddr)中
启动内核(已给定所加载DT的内存地址)

2.术语

本文和接下来关于dto的文章的一些术语解释

术语 含义
DT Device Tree
DTB Device Tree Blob
DTBO Device Tree Blob for Overlay
DTC Device Tree Compiler
DTO Device Tree Overlay
DTS Device Tree Source
FDT Flattened Device Tree, a binary format contained in a .dtb blob file

3. 实现DTO

实现DTO包含以下步骤:

  1. 分割设备树

  2. 构建

  3. 分区

  4. 运行

    同时,还必须保持两个DT之间的兼容性,并确定一个策略保证两个分区的安全性。

3.1 分割DT

将系统中的dt分割成两个部分:

  • 主 DT: 一般在kernel中,由SOC厂商提供,包含soc的默认配置
  • Overlay DT:由ODM/OEM提供,一般放在device中,包含某个device的特定配置

3.2 构建主DT和叠加层DT

构建主DT,执行以下操作:

  1. 将主DT的 .dts 编译为 .dtb 文件。
  2. 将 .dtb 文件刷写到bootloader在运行时可访问的分区。

如需构建叠加 DT,请执行以下操作:

  1. 将叠加DT .dts 编译为 .dtbo 文件。虽然此文件格式与格式设为扁平化设备树的 .dtb 文件相同,但是用不同的文件扩展名可
  2. 将其与主 DT 区分开来。
  3. 将 .dtbo 文件刷写到引导加载程序在运行时可访问的分区。

3.3 对DT进行分区

在闪存中确定bootloader在运行时可访问和可信的位置信息以放入 .dtb 和 .dtbo。

主DT的示例位置:

  • 作为boot分区的一部分,附加到内核 (image.gz)。
  • 单独的 DT blob (.dtb),位于专用分区 (dtb)。

叠加 DT 的示例位置:

如左图,将.dtbo单独放在一个分区,如dtbo分区
如右图,将 .dtbo 放入 odm 分区中(仅在您的bootloader能够从 odm 分区的文件系统中加载数据时才这样做)

注意: dtbo分区的大小取决于主dtb需要被更改的量,一般8M足够了。

对于支持无缝 (A/B) 更新的设备,请用 A/B 来标识主 DT 和叠加 DT 分区:

3.4 在bootloader中运行

如需运行,请执行以下操作:

  1. 将 .dtb 从存储空间加载到内存中。
  2. 将 .dtbo 从存储空间加载到内存中。
  3. 用 .dtb 叠加 .dtbo 以形成合并的 DT。
  4. 启动内核(已给定合并 DT 的内存地址)。

4. 保持兼容性

主 DTB(来自 SoC 供应商)会被视为 DTBO 的 API surface。将设备树分离为 SoC 通用部件和设备专用部件后,您必须确保这两个部件以后相互兼容,包括:

  • 主 DT 中的 DT 定义(例如,节点、属性、标签)。主 DT 中的任何定义更改都可能会触发叠加 DT 中的更改。例如,如需更正主 DT 中的某个节点名称,请定义映射到原始节点名称的“别名”标签(以免更改叠加 DT)。
  • 叠加 DT 的存储位置(例如,分区名称、存储格式)。

5. 确保安全

引导加载程序必须确保 DTB/DTBO 安全无虞、未被修改且未被损坏。您可以使用任何解决方案来保护 DTB/DTBO,例如,VBoot 1.0 中的启动映像签名或 AVB HASH footer (VBoot 2.0)。

  • 如果 DTB/DTBO 位于专属的分区中,您可以将该分区添加到 AVB 的信任链。信任链从硬件保护的信任根开始,并进入bootloader,从而验证 DTB/DTBO 分区的完整性和真实性。
  • 如果 DTB/DTBO 位于现有分区(如 odm 分区)中,该分区应位于 AVB 的信任链中。(DTBO 分区可以与 odm 分区共享一个公钥)。