泰晓科技 -- 聚焦 Linux - 追本溯源,见微知著!
网站地址:https://tinylab.org

泰晓实验箱:上手简单,配公开课
请稍侯

扁平化设备树 (DTB) 格式剖析之二:结构体块,字符串块和对齐

iOSDevLog 创作于 2022/10/18

Corrector: TinyCorrect v0.1-rc2 - [spaces urls pangu] Author: iOSDevLog iosdevlog@iosdevlog.com Date: 2022/08/18 Revisor: Fajie.WangNiXi YuHaoW1226@163.com; @taotieren admin@taotieren.com; Falcon falcon@tinylab.org Project: RISC-V Linux 内核剖析 Sponsor: PLCT Lab, ISCAS

上一篇文章介绍了 DTB 标准的版本,报头和内存保留块,这一篇文章继续介绍剩下的结构体块,字符串块和对齐。

Structure Block 结构体块

The structure block describes the structure and contents of the devicetree itself.

结构体块描述了设备树本身的结构和内容。

It is composed of a sequence of tokens with data, as described below.

它由一系列带有数据的令牌组成,如下所述。

These are organized into a linear tree structure, as described below.

这些被组织成线性树结构,如下所述。

Each token in the structure block, and thus the structure block itself, shall be located at a 4-byte aligned offset from the beginning of the devicetree blob.

结构体块中的每个令牌,以及结构体块本身,都应位于距设备树 blob 开头的 4 字节对齐偏移处。

Lexical structure 词汇结构

The structure block is composed of a sequence of pieces, each beginning with a token, that is, a big-endian 32-bit integer.

结构块由一系列片段组成,每个片段都以一个令牌开头,即一个大端 32 位整数。

Some tokens are followed by extra data, the format of which is determined by the token value.

一些令牌后面跟着额外的数据,其格式由令牌值决定。

All tokens shall be aligned on a 32-bit boundary, which may require padding bytes (with a value of 0x0) to be inserted after the previous token’s data.

所有令牌都应在 32 位边界上对齐,这可能需要在前一个令牌数据之后插入填充字节(值为 0x0)。

The five token types are as follows:

五种令牌类型如下:

FDT_BEGIN_NODE (0x00000001)

The FDT_BEGIN_NODE token marks the beginning of a node’s representation.

FDT_BEGIN_NODE 令牌标志着节点表示的开始。

It shall be followed by the node’s unit name as extra data.

它后面应跟有节点的单元名称作为额外数据。

The name is stored as a null-terminated string, and shall include the unit address, if any.

如果有名称的话,名称存储为以空字符结尾的字符串,并且应包括单元地址。

The node name is followed by zeroed padding bytes, if necessary for alignment, and then the next token, which may be any token except FDT_END.

如果需要对齐,节点名称后跟零填充字节,然后是下一个令牌,可以是除 FDT_END 之外的任何令牌。

FDT_END_NODE (0x00000002)

The FDT_END_NODE token marks the end of a node’s representation.

FDT_END_NODE 令牌标志着节点表示的结束。

This token has no extra data; so it is followed immediately by the next token, which may be any token except FDT_PROP.

这个令牌没有额外的数据;所以紧随其后的是下一个令牌,它可以是除 FDT_PROP 之外的任何令牌。

FDT_PROP (0x00000003)

The FDT_PROP token marks the beginning of the representation of one property in the devicetree.

FDT_PROP 令牌标志着设备树中一个属性表示的开始。

It shall be followed by extra data describing the property.

其后应是描述该属性的额外数据。

This data consists first of the property’s length and name represented as the following C structure:

该数据首先由属性的长度和名称组成,用以下 C 结构体表示:

struct fdt_property {
        fdt32_t tag;
        fdt32_t len;
        fdt32_t nameoff;
        char data[];
};

Both the fields in this structure are 32-bit big-endian integers.

此结构中的两个字段都是 32 位大端整数。

len gives the length of the property’s value in bytes (which may be zero, indicating an empty property).

len 以字节为单位给出属性值的长度(可能为零,表示一个空属性)。

nameoff gives an offset into the strings block at which the property’s name is stored as a null-terminated string.

nameoff 给出了字符串块的偏移量,在该块中属性的名称存储为以空字符结尾的字符串。

After this structure, the property’s value is given as a byte string of length len.

在此结构之后,属性的值作为长度为 len 的字节字符串给出。

This value is followed by zeroed padding bytes (if necessary) to align to the next 32-bit boundary and then the next token, which may be any token except FDT_END.

该值后跟有零填充字节(如有必要),以对齐下一个 32 位边界,然后是下一个令牌,该令牌可以是除 FDT_END 之外的任何令牌。

FDT_NOP (0x00000004)

The FDT_NOP token will be ignored by any program parsing the device tree.

FDT_NOP 令牌将被任何解析设备树的程序忽略。

This token has no extra data; so it is followed immediately by the next token, which can be any valid token.

这个令牌没有额外的数据;因此紧随其后的是下一个令牌,它可以是任何有效的令牌。

A property or node definition in the tree can be overwritten with FDT_NOP tokens to remove it from the tree without needing to move other sections of the tree’s representation in the devicetree blob.

树中的属性或节点定义可以用 FDT_NOP 令牌覆盖以将其从树中删除,而无需移动设备树 blob 中树状信息中的其他部分。

DT_END (0x00000009)

The FDT_END token marks the end of the structure block.

FDT_END 令牌标志着结构体块的结束。

There shall be only one FDT_END token, and it shall be the last token in the structure block.

应该只有一个 FDT_END 令牌,它应该是结构体块中的最后一个令牌。

It has no extra data.

它没有额外的数据。

so the byte immediately after the FDT_END token has offset from the beginning of the structure block equal to the value of the size_dt_struct field in the device tree blob header.

所以紧跟在 FDT_END 令牌之后的字节从结构体块的开头偏移,该偏移等于设备树 blob 报头中 size_dt_struct 字段的值。

Tree structure 树状结构

The devicetree structure is represented as a linear tree: the representation of each node begins with an FDT_BEGIN_NODE token and ends with an FDT_END_NODE token.

devicetree 结构表示为线性树:每个节点的表示以 FDT_BEGIN_NODE 令牌开始,以 FDT_END_NODE 令牌结束。

The node’s properties and subnodes (if any) are represented before the FDT_END_NODE, so that the FDT_BEGIN_NODE and FDT_END_NODE tokens for those subnodes are nested within those of the parent.

节点的属性和子节点(如果有)在 FDT_END_NODE 之前表示,因此这些子节点的 FDT_BEGIN_NODE 和 FDT_END_NODE 令牌嵌套在父节点的令牌中。

The structure block as a whole consists of the root node’s representation (which contains the representations for all other nodes), followed by an FDT_END token to mark the end of the structure block as a whole.

整个结构体块由根节点的表示(其中包含所有其他节点的表示)组成,后跟 FDT_END 令牌以标记整个结构体块的结尾。

More precisely, each node’s representation consists of the following components:

更准确地说,每个节点的表示由以下组件组成:

  • (optionally) any number of FDT_NOP tokens
  • (可选)任意数量的 FDT_NOP tokens
  • FDT_BEGIN_NODE token
  • FDT_BEGIN_NODE 令牌
    • The node’s name as a null-terminated string
    • 节点的名称作为以空字符结尾的字符串
    • [zeroed padding bytes to align to a 4-byte boundary]
    • 【对齐 4 字节边界填充字节零】
  • For each property of the node:
  • 对于节点的每个属性:
    • (optionally) any number of FDT_NOP tokens
    • (可选)任意数量的 FDT_NOP 令牌
    • FDT_PROP token
    • FDT_PROP 令牌
      • property information as given in Section 5.4.1
      • 第 5.4.1 节中给出的属性信息
      • [zeroed padding bytes to align to a 4-byte boundary]
      • 【对齐 4 字节边界填充字节零】
  • Representations of all child nodes in this format
  • 这种格式的所有子节点的表示
  • (optionally) any number of FDT_NOP tokens
  • (可选)任意数量的 FDT_NOP 令牌
  • FDT_END_NODE token
  • FDT_END_NODE 令牌

Note that this process requires that all property definitions for a particular node precede any subnode definitions for that node.

请注意,此过程要求特定节点的所有属性定义在该节点的任何子节点定义之前。

Although the structure would not be ambiguous if properties and subnodes were intermingled, the code needed to process a flat tree is simplified by this requirement.

虽然如果属性和子节点混合在一起,结构不会有歧义,但是处理扁平树所需的代码被这个要求简化了。

Strings Block 字符串块

The strings block contains strings representing all the property names used in the tree.

字符串块包含表示树中使用的所有属性名称的字符串。

These null terminated strings are simply concatenated together in this section, and referred to from the structure block by an offset into the strings block.

这些空终止字符串在本节中简单地连接在一起,并从结构体块中通过偏移量引用到字符串块中。

The strings block has no alignment constraints and may appear at any offset from the beginning of the devicetree blob.

字符串块没有对齐约束,可以出现在距设备树 blob 开头的任何偏移处。

Alignment 对齐

The devicetree blob shall be located at an 8-byte-aligned address.

设备树 blob 应位于 8 字节对齐的地址。

To maintain backwards compatibilty for 32-bit machines, 4-byte alignment is supported by some software, but this is not DTSpec-compliant.

为了保持 32 位计算机的向下兼容性,某些软件支持 4 字节对齐,但这不符合 DTSpec 标准。

For the data in the memory reservation and structure blocks to be used without unaligned memory accesses, they shall lie at suitably aligned memory addresses.

对于在不进行未对齐内存访问的情况下使用的内存预留和结构体块中的数据,它们应位于适当对齐的内存地址。

Specifically, the memory reservation block shall be aligned to an 8-byte boundary and the structure block to a 4-byte boundary.

具体而言,内存保留块应与 8 字节边界对齐,结构体块应与 4 字节边界对齐。

Furthermore, the devicetree blob as a whole can be relocated without destroying the alignment of the subblocks.

此外,可以在不破坏子块对齐的情况下重新定位整个设备树 blob。

As described in the previous sections, the structure and strings blocks shall have aligned offsets from the beginning of the devicetree blob.

如前几节所述,结构体块和字符串块应与设备树 blob 的开头对齐偏移。

To ensure the in-memory alignment of the blocks, it is sufficient to ensure that the devicetree as a whole is loaded at an address aligned to the largest alignment of any of the subblocks, that is, to an 8-byte boundary.

为了确保块在内存中的对齐,确保设备树作为一个整体被加载到与任何子块的 最大对齐 对齐的地址处,即 8 字节边界就足够了。

A DTSpec compliant boot program shall load the devicetree blob at such an aligned address before passing it to the client program.

符合 DTSpec 的引导程序应在这样的对齐地址加载设备树 blob,然后再将其传递给客户端程序。

If an DTSpec client program relocates the devicetree blob in memory, it should only do so to another 8-byte aligned address.

如果 DTSpec 客户端程序将设备树 blob 重新定位到内存中,它应该只将其重新定位到另一个 8 字节对齐的地址。

总结

本文参考 devicetree-specification-v0.4-rc1.pdf 第 5 章介绍扁平化设备树 (DTB) 格式剩下的结构体块,字符串块和对齐相关内容。

了解完扁平化设备树 (DTB) 格式之后,下一篇文章,我们将以一个真实的 DTB 文件的部分内容为例,使用图文结合的方式,详细介绍 DTB 格式展开后生成的设备树结构。

参考

  1. Devicetree Specification
  2. 5. Flattened Devicetree (DTB) Format


Read Album:

Read Related:

Read Latest: