编译和验证

您可以使用设备树编译器 (DTC) 来编译设备树源 (DTS) 文件。但是,在目标主 DT 上应用叠加设备树 (DT) 之前,您还应通过模拟设备树叠加 (DTO) 的行为来验证结果。

使用 DTC 编译

使用 dtc 编译 .dts 时,您必须添加选项 -@ 以在生成的 .dtbo 中添加 __symbols__ 节点。__symbols__ 节点包含使用标签标记的所有节点的列表,DTO 库可以使用这些节点进行引用。

构建主 DT .dts 的示例命令

dtc -@ -O dtb -o my_main_dt.dtb my_main_dt.dts

构建叠加 DT .dts 的示例命令

dtc -@ -O dtb -o my_overlay_dt.dtbo my_overlay_dt.dts

在主机上验证 DTO 结果

验证可以帮助您识别在主 DT 上放置叠加 DT 时可能发生的错误。在更新目标之前,您可以通过使用 .dts 中的 /include/ 模拟 DTO 的行为,从而在主机上验证叠加 DT 的结果。

图 1. 使用语法 /include/ 在主机上模拟 DTO。

  1. 创建叠加 .dts 的副本。在副本中,删除第一行标头。示例
    /dts-v1/;
    /plugin/;
    
    将文件另存为 my_overlay_dt_wo_header.dts(或您想要的任何文件名)。
  2. 创建主 .dts 的副本。在副本中,在最后一行之后,附加您在步骤 1 中创建的文件的 include 语法。例如
    /include/ "my_overlay_dt_wo_header.dts"
    
    将文件另存为 my_main_dt_with_include.dts(或您想要的任何文件名)。
  3. 使用 dtc 编译 my_main_dt_with_include.dts 以获取合并的 DT,它应该与 DTO 的结果相同。例如
    dtc -@ -O dtb -o my_merged_dt.dtb my_main_dt_with_include.dts
    
  4. 使用 dtc 转储 my_merged_dt.dto
    dtc -O dts -o my_merged_dt.dts my_merged_dt.dtb
    

在 Android 9 中验证 DTO

Android 9 需要设备树 blob 叠加 (DTBO) 分区。为了在 SoC DT 中添加节点或更改属性,引导加载程序必须动态地将设备特定的 DT 叠加在 SoC DT 上。

指示已应用的叠加层

为了使 供应商测试套件 (VTS) 能够评估叠加应用的正确性,供应商必须添加一个新的内核命令行参数 androidboot.dtbo_idx,以指示从 DTBO 分区中选择的叠加层。在使用内核版本 5.10 或更高版本的 Android 12 中,此参数通过 bootconfig 传递。例如,参数 androidboot.dtbo_idx=x,y,z 报告 xyz 是引导加载程序按顺序从 DTBO 分区应用到基本 DT 的 DTO 的从零开始的索引。

叠加层可以应用于主 DT 中的节点或添加新节点,但不能引用先前叠加层中添加的节点。此限制是必要的,因为叠加应用不会将叠加符号表与主 DT 符号表合并(不合并可以避免符号名称冲突和叠加层之间依赖关系的复杂化)。

示例:无效的叠加层

在此示例中,overlay_2.dts 引用了节点 e,该节点由 overlay_1.dts 添加。在将 overlay_1 应用于主 DT 后,如果尝试将 overlay_2 应用于生成的 DT,则叠加应用将失败,并显示错误,指出符号 e 不在基本 DT 的符号表中。

main.dts overlay_1.dts overlay_2.dts
[main.dts]

/dts-v1/;

/ {
  a: a {};
  b: b {};
  c: c {};
};
[overlay_1.dts]

/dts-v1/;
/plugin/;

&b { ref1 =  <&a>;
    e: e {
        prop = <0x0a>;
        phandle = <0x04>;
    };
};
[overlay_2.dts]

/dts-v1/;
/plugin/;

/* invalid! */
&e {
    prop = <0x0b>;
};

示例:有效的叠加层

在此示例中,overlay_2.dts 仅引用来自主 DTS 的节点 b。当将 overlay_1 应用于基本 DT,然后应用 overlay_2 时,节点 e 中属性 prop 的值(由 overlay_1.dts 设置)将被 overlay_2.dts 设置的值覆盖。

main.dts overlay_1.dts overlay_2.dts
[final.dts]

/dts-v1/;

/ {
  a: a {};
  b: b {};
  c: c {};
};
[overlay_1.dts]

/dts-v1/;
/plugin/;


&b { ref1 =  <&a>;
     e {
          prop = <0x0c>;
      };
};
[overlay_2.dts]

/dts-v1/;
/plugin/;

/* valid */
&b { ref1 =  <&c>;
     e {
          prop = <0x0d>;
      };
};

实现 DTBO 分区

要实现所需的 DTBO 分区,请确保引导加载程序可以执行以下操作

  1. 识别它正在运行的板,并选择要应用的相应叠加层。
  2. androidboot.dtbo_idx 参数附加到内核命令行。
    • 该参数必须指示它应用到基本 DT 的 DTBO 分区映像中的 DTO 的从零开始的索引(按相同顺序)。
    • 索引必须引用叠加层在 DTBO 分区中的位置。

有关 DTBO 分区结构的详细信息,请参阅设备树叠加层

验证 DTBO 分区

您可以使用 VTS 验证以下内容

  • 内核命令行参数 androidboot.dtbo_idx 的存在(通过检查 Init 是否已自动设置相应的 ro.boot.dtbo_idx 系统属性)。
  • ro.boot.dtbo_idx 系统属性的有效性(通过检查该属性是否指定至少一个有效的 DTBO 映像索引)。
  • DTBO 分区的有效性(还验证应用于基本 DT 的 DTBO 分区中的叠加层)。
  • 结果 DT 中的其他节点或属性更改将呈现给 Linux 内核。

例如,在以下叠加层和最终 DT 中,将 androidboot.dtbo_idx=5,3 添加到内核命令行会通过验证,但将 androidboot.dtbo_idx=3,5 添加到内核命令行不会通过验证。

索引 3 处的叠加 DT 索引 5 处的叠加 DT
[overlay_1.dts]

/dts-v1/;
/plugin/;

&c { prop = <0xfe>; };
[overlay_2.dts]

/dts-v1/;
/plugin/;

&c { prop = <0xff>; };
最终 DT
/dts-v1/;
/ {

	a {
		phandle = <0x1>;
	};

	b {
		phandle = <0x2>;
	};

	c {
		phandle = <0x3>;
		prop = <0xfe>;
	};

	__symbols__ {
		a = "/a";
		b = "/b";
		c = "/c";
	};
};