当前位置: 首页 > news >正文

Android的DTBO详解

在这里插入图片描述

文章目录

      • 1. 核心概念:什么是 DTB/DTBO?
      • 2. DTBO 要解决什么问题?(为什么需要它?)
      • 3. DTBO 的工作原理:叠加(Overlay)
      • 4. 技术细节:DTBO 镜像格式
      • 5. 如何创建和操作 DTBO?
      • 6. 总结与重要性

今天详细深入地介绍一下 Android 的 DTBO。

1. 核心概念:什么是 DTB/DTBO?

要理解 DTBO,首先要了解它的基础:设备树(Device Tree)

  • 设备树(Device Tree): 是一种描述硬件配置的数据结构。它以一种与平台无关的格式,详细说明了处理器类型、内存大小、总线、外设(如I2C、SPI设备)、中断线、GPIO引脚等硬件信息。它的出现是为了解决内核需要为成千上万种不同的硬件板卡提供支持的冗余代码问题。简单说,它就是一个“硬件配置清单”。
  • 设备树二进制文件(DTB, Device Tree Blob): 设备树源文件(.dts)被编译后生成的二进制文件。Bootloader 会将它加载到内存中,并传递给 Linux 内核。内核解析这个 DTB 文件来了解当前设备的硬件布局,从而正确地初始化驱动程序。
  • 设备树叠加层二进制文件(DTBO, Device Tree Overlay Blob): 这是 Android 引入的概念。它是一个增量补丁形式的设备树二进制片段。它的目的不是描述整个硬件,而是为了动态地修改主设备树(DTB)的内容。

2. DTBO 要解决什么问题?(为什么需要它?)

在传统的嵌入式Linux中,一个设备对应一个特定的DTB文件。但Android设备,特别是现代手机,面临更复杂的场景:

  1. 硬件碎片化与通用系统映像(GSI)

    • Google 推出了 Project Treble,要求将 Android 操作系统框架与设备特定的底层硬件驱动(Vendor Implementation)分离。
    • 为了实现一个通用系统映像(GSI) 能在多个不同硬件的设备上运行,GSI 内核必须是通用的。但这个通用内核的 DTB 不可能包含所有设备的硬件信息。
    • 解决方案: GSI 使用一个通用的基础 DTB,而每个特定设备则提供一个 DTBO 文件。在启动时,Bootloader 将基础 DTB 和针对该设备的 DTBO 合并,形成一个完整的、描述本机硬件的设备树。
  2. A/B 系统更新(Seamless Updates)

    • 许多设备支持 A/B 分区,有两个系统分区(system_a, system_b)以便无缝更新。
    • 虽然系统分区可以不同,但 boot 分区(包含内核和DTB)通常是被共享的。如果两个系统槽位需要不同的硬件配置(例如,一个槽位用于正常启动,另一个用于调试或特殊模式),单一的 DTB 就无法满足需求。
    • 解决方案: 共享的 boot 分区包含基础 DTB,而每个系统槽位(vendor_a, vendor_b)可以有自己的 DTBO 文件。Bootloader 根据当前激活的槽位,选择对应的 DTBO 与基础 DTB 合并。
  3. 单一系统映像支持多种硬件变体(SKU)

    • 同一款手机型号可能有多种硬件变体(例如,不同地区的版本使用的 NFC 芯片、摄像头传感器或屏幕可能不同)。
    • 为每个变体都编译一个独立的 boot.img 会增加维护和测试的复杂度。
    • 解决方案: 所有变体共享一个基础的 boot.img(包含基础 DTB)。每个硬件变体有一个独特的 DTBO 文件。Bootloader 通过读取硬件ID(如PCB版本号),动态选择正确的 DTBO 进行叠加,从而让同一份内核和系统能够适配不同的硬件。

3. DTBO 的工作原理:叠加(Overlay)

DTBO 的核心思想是“叠加”。你可以把它想象成在一张基础地图(基础DTB)上贴上一张透明的修正贴纸(DTBO)。

  • 新增节点: DTBO 可以添加一个在基础 DTB 中不存在的全新设备节点。
    • 例如: 为基础 DTB 中添加一个新的 nfc@78 I2C 设备节点。
  • 修改属性: DTBO 可以修改基础 DTB 中已有节点的属性值。
    • 例如: 修改 memory 节点的 size 属性,以适配不同内存大小的版本。
    • 例如: 修改 gpio-keys 的中断号,因为不同硬件版本的按键所连接的GPIO引脚可能不同。
  • 删除节点/属性(理论上支持,但较少使用): 可以标记基础 DTB 中的某个节点或属性为已删除。

工作流程:

  1. Bootloader 加载通用的基础 DTB(通常来自 boot.imgdtb.img)。
  2. Bootloader 根据当前的硬件ID或系统槽位,从 dtbo.img(一个DTBO分区)或 vendor 分区中加载对应的 DTBO 文件。
  3. Bootloader 中的设备树叠加层支持(libufdt 或 fdtoverlay)将 DTBO 应用到基础 DTB 上,合并生成一个最终的、完整的设备树。
  4. Bootloader 将这个合并后的设备树传递给 Linux 内核。
  5. 内核解析这个最终的设备树,初始化硬件。

4. 技术细节:DTBO 镜像格式

多个 DTBO 文件通常被打包在一个专用的 dtbo.img 镜像文件中。这个镜像有特定的格式:

  • 文件头(dt_table_header): 包含魔数、总DTBO条目数、每个DTBO条目的大小等。
  • 条目表(dt_table_entry): 一个数组,每个元素描述一个 DTBO 片段在镜像中的偏移量、大小、以及相关的ID或版本信息。
  • DTBO Blobs: 实际的多个 DTBO 二进制数据块。

Bootloader 会解析这个 dtbo.img 的头,然后根据匹配条件(如硬件版本 dtbo.board_id)找到正确的那个 DTBO 块。


5. 如何创建和操作 DTBO?

  1. 编写设备树源文件

    • 基础设备树:base.dts
    • 叠加层设备树:overlay.dts。它的开头必须有一个 /plugin/; 标签,这表明它是一个叠加层片段,而不是一个完整的设备树。
      /dts-v1/;
      /plugin/;&i2c_3 { // 这是一个引用,指向基础DTB中的i2c_3节点status = "okay";#address-cells = <1>;#size-cells = <0>;nfc@28 {compatible = "nxp,pn544";reg = <0x28>;interrupt-parent = <&tlmm>;interrupts = <61 0>;enable-gpios = <&tlmm 62 0>;};
      };
      
  2. 编译

    • 使用设备树编译器(DTC)来编译它们。
    # 编译基础 DTB
    dtc -O dtb -o base.dtb base.dts# 编译叠加层 DTBO
    dtc -O dtb -o overlay.dtbo overlay.dts
    
  3. 打包成 dtbo.img

    • 使用 mkdtboimg.py(AOSP 中的工具)将多个 .dtbo 文件打包。
    mkdtboimg.py create dtbo.img \--id=0x1000 overlay_v1.dtbo \--id=0x1001 overlay_v2.dtbo
    
  4. 在 Bootloader 中配置

    • 设备制造商需要在其 Bootloader(如 U-Boot 或 Little Kernel)中实现叠加逻辑,通常通过 libufdt 库来解析和应用叠加层。

6. 总结与重要性

特性传统单一 DTBAndroid DTBO + DTB
灵活性低,一机一镜像,一镜像多机型,支持GSI
维护性差,每个硬件变更都需新boot.img,仅需更新独立的DTBO文件
A/B 系统支持困难天然支持,不同槽位可配不同DTBO
镜像大小较大(多个boot.img)较小(共享基础boot.img)

DTBO 是 Project TrebleGeneric System Image (GSI) 能够成功实现的基石技术之一。它通过将硬件配置从核心内核镜像中解耦出来,极大地提升了 Android 生态系统的模块化、可维护性和更新效率,让 OEM 厂商能够更灵活地应对多种硬件配置,也让开发者能够更容易地为设备构建通用的系统。


结束语
Flutter是一个由Google开发的开源UI工具包,它可以让您在不同平台上创建高质量、美观的应用程序,而无需编写大量平台特定的代码。我将学习和深入研究Flutter的方方面面。从基础知识到高级技巧,从UI设计到性能优化,欢饮关注一起讨论学习,共同进入Flutter的精彩世界!

http://www.xdnf.cn/news/1468765.html

相关文章:

  • SQL Server 原生备份与第三方备份:哪个更适合您的组织?
  • 服务器测试网速教程:基于iperf进行测试带宽
  • 基于单片机金属探测器设计
  • 「数据获取」《中国包装业发展研究报告(2008)》
  • 人大金仓:创建数据库分区
  • AI助力决策:告别生活与工作中的纠结,明析抉择引领明智选择
  • 基于单片机老人居家环境健康检测/身体健康检测设计
  • EI会议:第三届大数据、计算智能与应用国际会议(BDCIA 2025)
  • 解释一下roberta,bert-chinese和bert-case有啥区别还有bert-large这些
  • 大基座模型与 Scaling Law:AI 时代的逻辑与困境
  • AAB包转apks转apk
  • docker重启redis报错:iptables failed
  • 边缘计算设备+深度学习辅导
  • 信息系统安全保护措施文件方案
  • Selenium元素定位终极指南:8种方式全面解析+实战代码,告别找不到元素的烦恼!
  • IPD变革,是中国企业实现产品与技术领先之路
  • 使用tomcat本地部署draw.io
  • 项目管理方法与企业战略目标如何对齐
  • VQ-VAE-2:开启高保真多样化图像生成的新范式
  • maven只使用本地仓库依赖
  • Maven常见问题解决方案
  • 关于Homebrew:Mac快速安装Homebrew
  • 七彩喜微高压氧舱:科技与体验的双重革新,重新定义家用氧疗新标杆
  • AI配音工具哪个好用?7款热门配音软件推荐指南!
  • 数据加盐处理(密码加盐)
  • webpack笔记
  • Golang Goroutine 与 Channel:构建高效并发程序的基石
  • Django REST framework:SimpleRouter 使用指南
  • uniapp开发小程序,列表 点击后加载更多数据
  • 国产测头如何破解三坐标测量“精度+效率”双重难题?