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.c2
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