linux设备树dts的节点device_node处理流程

一、kernel对dts解析函数调用过程

start_kernel // init/main.c
    setup_arch(&command_line);  // arch/arm/kernel/setup.c
        mdesc = setup_machine_fdt(__atags_pointer);  // arch/arm/kernel/devtree.c
                    //扫描dts节点
                    early_init_dt_scan_nodes();      // drivers/of/ftd.c
                        /* Retrieve various information from the /chosen node */
                        //处理bootargs
                        of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
                        /* Initialize {size,address}-cells info */
                        of_scan_flat_dt(early_init_dt_scan_root, NULL);
                        /* Setup memory, calling early_init_dt_add_memory_arch */
                        of_scan_flat_dt(early_init_dt_scan_memory, NULL);

二、kernel对dts解析函数调用解释

a. /chosen节点中bootargs属性的值, 存入全局变量: boot_command_line
b. 确定根节点的这2个属性的值: #address-cells, #size-cells
存入全局变量: dt_root_addr_cells, dt_root_size_cells
c. 解析/memory中的reg属性, 提取出"base, size", 最终调用memblock_add(base, size);

三、kernel将_dtb转换为device_node

a.在DTB文件中,

每一个节点都以TAG(FDT_BEGIN_NODE, 0x00000001)开始, 节点内部可以嵌套其他节点,
每一个属性都以TAG(FDT_PROP, 0x00000003)开始

b. 每一个dtb节点kernel都转换为一个device_node结构体:

struct device_node {
    
    
    const char *name;  // 来自节点中的name属性, 如果没有该属性, 则设为"NULL"
    const char *type;  // 来自节点中的device_type属性, 如果没有该属性, 则设为"NULL"
    phandle phandle;
    const char *full_name;  // 节点的名字, node-name[@unit-address]
    struct fwnode_handle fwnode;

    struct  property *properties;  // 节点的属性
    struct  property *deadprops;    /* removed properties */
    struct  device_node *parent;   // 节点的父亲
    struct  device_node *child;    // 节点的孩子(子节点)
    struct  device_node *sibling;  // 节点的兄弟(同级节点)
#if defined(CONFIG_OF_KOBJ)
    struct  kobject kobj;
#endif
    unsigned long _flags;
    void    *data;
#if defined(CONFIG_SPARC)
    const char *path_component_name;
    unsigned int unique_id;
    struct of_irq_controller *irq_trans;
#endif
};

c. device_node结构体中有properties, 用来表示该节点的属性

每一个属性对应一个property结构体:

struct property {
    
    
    char    *name;    // 属性名字, 指向dtb文件中的字符串
    int length;       // 属性值的长度
    void    *value;   // 属性值, 指向dtb文件中value所在位置, 数据仍以big endian存储
    struct property *next;
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
    unsigned long _flags;
#endif
#if defined(CONFIG_OF_PROMTREE)
    unsigned int unique_id;
#endif
#if defined(CONFIG_OF_KOBJ)
    struct bin_attribute attr;
#endif
};
   

d. 这些device_node构成一棵树, 根节点为: of_root

四、device_node树状图

在这里插入图片描述
五、kernel中device_node结构体获取dts调用过程

start_kernel // init/main.c
    setup_arch(&command_line);  // arch/arm/kernel/setup.c
        arm_memblock_init(mdesc);   // arch/arm/kernel/setup.c
            early_init_fdt_reserve_self();
                    /* Reserve the dtb region */
                    // 把DTB所占区域保留下来, 即调用: memblock_reserve
                    early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
                                      fdt_totalsize(initial_boot_params),
                                      0);           
            early_init_fdt_scan_reserved_mem();  // 根据dtb中的memreserve信息, 调用memblock_reserve
            
        unflatten_device_tree();    // arch/arm/kernel/setup.c
            __unflatten_device_tree(initial_boot_params, NULL, &of_root,
                        early_init_dt_alloc_memory_arch, false);            // drivers/of/fdt.c
                
                /* First pass, scan for size */
                size = unflatten_dt_nodes(blob, NULL, dad, NULL);
                
                /* Allocate memory for the expanded device tree */
                mem = dt_alloc(size + 4, __alignof__(struct device_node));
                
                /* Second pass, do actual unflattening */
                unflatten_dt_nodes(blob, mem, dad, mynodes);
                    populate_node
                        np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl,
                                    __alignof__(struct device_node));
                        
                        np->full_name = fn = ((char *)np) + sizeof(*np);
                        
                        populate_properties
                                pp = unflatten_dt_alloc(mem, sizeof(struct property),
                                            __alignof__(struct property));
                            
                                pp->name   = (char *)pname;
                                pp->length = sz;
                                pp->value  = (__be32 *)val;

猜你喜欢

转载自blog.csdn.net/qq_18077275/article/details/108852074