09、设备树dtb信息转化为device_node结构
一、初始化流程
在系统初始化的过程中,我们需要将DTB
转换成节点是device_node
的树状结构,以便后续方便操作。具体的代码位于setup_arch->unflatten_device_tree
中。
二、dtb转换为device_node
2.1、device_node结构图
当内核处理Device Tree中的每个节点时,它会为每个节点创建一个对应的struct device_node结构体。最终,这些结构体会被关联到具体的硬件设备管理结构体struct device上。
struct device_node
结构体描述如下:
struct device_node {
const char *name; /* name属性的值, 没有为<NULL> */
const char *type; /* device_type属性的值,没有为<NULL> */
phandle phandle; /* 可用于其他节点引用的标记 */
const char *full_name; /* 节点名称 */
struct fwnode_handle fwnode;
struct property *properties; /* 指向该设备节点下的第一个属性,其他属性与该属性链表相接 */
struct property *deadprops; /* removed properties */
struct device_node *parent; /* 设备的父节点 */
struct device_node *child; /* 设备子节点 */
struct device_node *sibling; /* 设备兄弟节点 */
struct kobject kobj;
unsigned long _flags;
void *data;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2.2、Property
kernel
会根据Device Tree
中所有的属性解析出数据填充struct property
结构体。
struct property
结构体描述如下:
kernel
根据Device Tree
的文件结构信息转换成struct property
结构体, 并将同一个node
节点下面的所有属性通过property.next
指针进行链接, 形成一个单链表。
三、unflatten_device_tree调用上下文
函数调用关系:
start_kernel // init/main.c
--->setup_arch(&command_line); // arch/arm/kernel/setup.c
--->unflatten_device_tree(); // msm-4.14\drivers\of\fdt.c
2
3
4
3.1、unflatten_device_tree
drivers/of/fdt.c
参数initial_boot_params
为dtb
文件的起始地址,of_root
用于保存device_node
的根节点, 以后可以通过该变量找到所有的设备节点, early_init_dt_alloc_memory_arch
该参数为回调函数用于分配内存给设备节点使用;
3.2、__unflatten_device_tree
①: 用于计算Device Tree
转换成struct device_node
和struct property
结构体需要分配的内存大小;
②: 调用回调函数根据unflatten_dt_node()
计算出的size
分配内存;
③: 填充每一个struct device_node
和struct property
结构体;
这个函数中调用了两次unflatten_dt_node(), 但是两次调用的含义是不同的;
3.3、unflatten_dt_node
①: 调用fdt_get_name()
获取该节点名称;②: 特殊处理根节点将要分配的内存大小;③: 从mem
中为该设备节点分配内存,size为sizeof(struct device_node) + allocl
, allocl
为节点名字长度;④: 成员full_name
和变量 fn
都指向该设备节点data
成员, 接着将节点名字赋值给fn
变量, 即如下图所示:
fdt_next_node
目录:scripts/dtc/libfdt/fdt.c
populate_node