一、DTS文件综述
最新的UBOOT代码支持OF(Open Firmware)结构的扁平设备树(flattened device-tree),目前还没有对OF结构的用户接口API进行支持。因此,在U-boot向Linux内核跳转的时候需要向内核传递一张描述整个硬件系统扁平设备树的的表,来描述设备、总线以及中断的信息等等。这个表被称为设备树块(device-tree block),也就是我们提供的二进制dtb文件。我们一般不对该二进制文件进行直接编辑,而是通过一定硬件描述语法创建一个dts(device-tree source)文件,再用特定的工具dtc将dts转成目标dtb文件。
1.U-BOOT传递给Linux PowerPC的参数
Linux PowerPC有且仅有一个单一的入口点,该入口点支持下面两种调用习俗,而其中第一种正是目前UBOOT启动Linux内核采用的方法,因为UBOOT只支持OF结构的扁平设备树。(参见下表)
a) 启动方式一:BOOT支持OF扁平设备树
b) 启动方式二:BOOT全面支持OF结构(包括用户接口API和OF扁平设备树)
word注释表-1 两种BOOT启动Linux内核的方式
Linux内核中的参数 | BOOT支持OF扁平设备树 | BOOT全面支持OF结构(包括用户接口API和OF扁平设备树) |
通用寄存器r3 | 指向内存中设备树块 | 指向OF用户接口API的地址 |
通用寄存器r4 | 指向Linux内核所在的物理地址 | 微波炉功率Initrd的起始地址 |
通用寄存器r5 | 空 | Initrd的长度 |
土豆粉蒸肉通用寄存器r6 | 空 | 命令行参数起始地址 |
通用寄存器r7 | 空 | 命令行参数结束地址 |
| | 梁漱溟读音 |
2.设备树(Device Tree)块格式
注意:设备树块必需位于主内存中。它可以通过内存的“实模式”和“虚模式”获取到。
1)报头
进入内核时,r3指向由include/asm-powerpc/prom.h中boot_param_header结构简要描述的内存区。
struct boot_param_header {
u32 magic; /* magic word OF_DT_HEADER */
u32 totalsize; /* total size of DT block */
u32 off_dt_struct; /*offt to structure */
u32 off_dt_strings; /*offt to strings */
u32 off_mem_rsvmap; /* offt to memory rerve map*/
u32 version; /* format version */
u32 last_comp_version; /* last compatible version */
/* version 2fields below */
u32 boot_cpuid_phys; /* Which physical CPU id we're bootingon */
/* version 3fields below */
u32 size_dt_strings; /* size of the strings block */
/* version 17fields below */
u32 size_dt_struct; /* size of the DT structure block */
};
苏州中考录取分数线
典型的DT块内存设计格式如下(地址从高端到底端):
图-1 DT块的结构图
(*)alignment gaps不是必需存在的,它们的存在和大小依赖于单个数据块的各种对齐要求。
2)设备树一般性
设备树自身被分割成两个不同的块,一个“结构块”,和一个“字符串块”。两个块都需要四字节对齐。
首先在祥述存储格式之前,我们快述的描述设备树概念。
顾名思义,设备树是一颗树,所以,除了root节点没有“parent”外,所有节点有且仅有几个“parent”节点。
每个节点都有两个名字,“实际节点名”:包含在节点属性列表中的属性类型名。它的值是一串以“0”终止的字符串。
还有一个“单元节点名(unit name)”,它用于区分同一级别的相同名字的节点。“@”标记,和“unit address”用来定义节点所在的总线类型。
苹果有维生素c吗
“unit name”没有当作一个单个的属性存在,而是包含在设备树结构中。典型用于代表设备树的“path”。
蒙在鼓里的意思每个节点(node)实际上代表一个实际的设备(更确切的说,该节点不仅仅是许多节点的一个虚拟“容器”,例如:“/cpus”)。每个节点也需要包括一个“device_type”属性,来指示节点的类型。
最后,每个节点都可以被其它节点参考,通过一个“linux,phandle”属性来表示。然而,如果直接使用平坦设备树,那麽该属性是可选的。
“linux,phandle”属性是一个32位的独一无二的值,用来识别一个节点。你可以自由的使用任何值或系统值、内部指针、或任何其它东西来产生这些值。唯一需求是:你提供给每一个节点的属性是独一无二的。
下面是一个简单设备树的的实例。在该例子中,“o”指示一个节点,紧跟其后的是节点“unit name”。属性是那些紧跟节点名后的内容。这些“内容”呈现出一串ASCII码字符串(以0终止)值,而“内容”以32位十六进制值表示。
/
o device-tree
|- name = "device-tree"
|- model = "MyBoardName"
|- compatible ="MyBoardFamilyName"
|- #address-cells = <2>
|- #size-cells = <2>
|- linux,phandle = <0>
|
o cpus
| | - name = "cpus"
| | - linux,phandle = <1>
| | - #address-cells = <1>
| | - #size-cells = <0>
| |
| o PowerPC,970@0
| |- name = "PowerPC,970"
| |- device_type = "cpu"
| |- reg = <0>
| |- clock-frequency = <5f5e1000>
| |- 64-bit
| |- linux,phandle = <2>
|
o memory@0
| |- name = "memory"
| |- device_type = "memory"
| |- reg = <00000000 00000000 0000000020000000>
| |- linux,phandle = <3>
对爱情的理解
|
o chon
|- name = "chon"
|- bootargs = "root=/dev/sda2"
|- linux,phandle = <4>
3)设备树“结构”块
设备树结构是一个线性的树型结构。“OF_DT_BEGIN_NODE”标记开始一个节点,“OF_DT_END_NODE”标记结束一个节点定义。孩子节点简单的定义在“OF_DT_END_NODE”之前。一个“标记”是一个32位的值。 设备树以“OF_DT_END”标记结束。
下面是单个节点的基本结构:
* 标记OF_DT_BEGIN_NODE (也就是0x00000001)
* 对于版本 1 to 3,这是一个以0中止的字符串表示的节点完全路径,
以“/”起始。对于版本16或更高版本,这仅仅是一个节点“node name”
(或对于root节点,为空字符串)
* [四字界边界对其的间隙]
* 对于每一个属性:
* 标记OF_DT_PROP (也就是0x00000003)
* 32-bit 的属性值,以字节表示的大小 (如果没有值,为0)
* 属性名的字符串块的32为偏移值
* 属性值数据(如果存在)
* [四字界边界对其的间隙]
* [孩子节点(如果存在)]
* 标记OF_DT_END_NODE (也就是0x00000002)
所以,节点内容可以概要为:一个起始标记,一个完整的路径,一个属性列表,一个孩子节点列表,和一个结束标记。每一个孩子节点都是上述定义的完全节点结构。
4)设备树“字符串”块
为了节省空间,属性名通常是冗余的,被单独存储在“字符串”块中。该块是整串以0为终止字符的字符串属性名连接在一起的简单块区域。Structure块中的设备树定义会包含从字符串块开始的偏移值。
3.需要的设备树内容
1)有关cells和address表示法的注释
通用的规则由各种各样的Open Firmware文档定义。如果你选择使用设备树来描述一条总线(bus),并且存在一条OF bus binding,那麽你应该遵守这个规格。内核不需要设备树来描述每单个设备或总线。
通常,一个设备的地址格式由parent总线类型定义,基于#address-cells和#size-cells属性。如果缺少该属性,那麽parent’s parent被使用,依次类推…。内核需要root节点具有那些属性,来定义直接映射到处理器总线上设备的地址格式。
这两个属性定义“cells”来表示地址(address)和大小(size)。“cell”是一个32位的号码。例如,上面例子的每个属性都包含2,那麽地址(address)和大小(size)都由2 cells组成,并且每个都有64位数字组成(cells被连接,并且被预计为big endian格式)。大多数32位的实现应该定义#address-cells和#size-cells为1,它代表一个32位的值。一些32位的处理器允许物理地址超过32位,那麽这些处理器应该定义#address-cells为2。
“reg”属性总是“address size”类型的组合,其中cells的address和size数目由总线的“#address-cells”和“size-cells”指定。当一条总线支持各种各样的地址空间,并且其它标志与给予的地址分配对应(象:可预取的,等等),那些标志通常被加到物理地址的top位中。例如,PCI物理总线由3个cells组成,bottom 2 cells包含自身实际的地址,而top cell包含地址空间指示,标志,和PCI总线&设备号。