当前位置: 首页 > news >正文

linux root节点解析

首先来看看root节点解析大体调用流程
在这里插入图片描述
这里只关注具体的解析函数的实现,中间的调用流程可以看上图自行跟踪。这里从unflatten_device_tree函数调用开始分析其实现:

unflatten_device_tree

void __init unflatten_device_tree(void)
{__unflatten_device_tree(initial_boot_params, NULL, &of_root,early_init_dt_alloc_memory_arch, false);of_alias_scan(early_init_dt_alloc_memory_arch);unittest_unflatten_overlay_base();
}

这个函数主要有两点:
1、具体的解析root节点
2、解析节点别名和向内核传递参数

__unflatten_device_tree

在这里插入图片描述
由上述可知unflatten_dt_nodes此函数是具体的解析函数,被调用了两次。一次传递的是NULL用以获取设备树信息的总大小,二次才是根据第一次获取大小分配内存保存数据。下面来具体的分配此函数的实现

unflatten_dt_nodes

static int unflatten_dt_nodes(const void *blob,void *mem,struct device_node *dad,struct device_node **nodepp)
{struct device_node *root;int offset = 0, depth = 0, initial_depth = 0;
#define FDT_MAX_DEPTH	64 //支持的最大节点深度为64struct device_node *nps[FDT_MAX_DEPTH];void *base = mem;bool dryrun = !base;int ret;if (nodepp)*nodepp = NULL;if (dad)depth = initial_depth = 1;root = dad;nps[depth] = dad;//使用广度优先,优先解析相邻节点for (offset = 0;offset >= 0 && depth >= initial_depth;offset = fdt_next_node(blob, offset, &depth)) {if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH - 1))continue;//节点status不为oa/okay跳过if (!IS_ENABLED(CONFIG_OF_KOBJ) &&!of_fdt_device_is_available(blob, offset))continue;//具体的解析函数ret = populate_node(blob, offset, &mem, nps[depth],&nps[depth+1], dryrun);if (ret < 0)return ret;if (!dryrun && nodepp && !*nodepp)*nodepp = nps[depth+1];//保存根节点of_rootif (!dryrun && !root)root = nps[depth+1];//}if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {pr_err("Error %d processing FDT\n", offset);return -EINVAL;}/** Reverse the child list. Some drivers assumes node order matches .dts* node order*/if (!dryrun)reverse_nodes(root);return mem - base;
}

populate_node

在这里插入图片描述
插入操作可以用下图来理解:
插入前
插入前
在这里插入图片描述
插入后
从上图可以这里的结构相当单链表,只不过所有的子节点都会指向父点。父节点只需拿到child节点,就可以轮询所有的子节点。以of_root根节点为首,就可以遍历到所有的子节点。
下面再来看看,当前节点的属性解析

populate_properties

在这里插入图片描述
这里需要注意的是链表的插入操作,一直使用pprev变量取最尾部结构体成员next的地址,链表尾部的成员next肯定为NULL,但其地址不为NULL。插入操作是将地址的内容指向当前的的pp,基本就是单链表尾部插入。大体示意图如下:
在这里插入图片描述
到这里device_node的节点解析以及节点里面的属性解析都已经走完了,剩下的就是重复操作直到将整个DTS解析完成。

of_alias_scan

void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
{struct property *pp;of_aliases = of_find_node_by_path("/aliases");of_chosen = of_find_node_by_path("/chosen");if (of_chosen == NULL)of_chosen = of_find_node_by_path("/chosen@0");if (of_chosen) {/* linux,stdout-path and /aliases/stdout are for legacy compatibility */const char *name = NULL;if (of_property_read_string(of_chosen, "stdout-path", &name))of_property_read_string(of_chosen, "linux,stdout-path",&name);if (IS_ENABLED(CONFIG_PPC) && !name)of_property_read_string(of_aliases, "stdout", &name);if (name)of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);if (of_stdout)of_stdout->fwnode.flags |= FWNODE_FLAG_BEST_EFFORT;}if (!of_aliases)return;for_each_property_of_node(of_aliases, pp) {const char *start = pp->name;

这里主要解析了两个比较特别的属性/aliases和/chosen,其中/aliases是节点别名。/chosen配置一些内核参数 比如cmdline。拿到/aliases后会解析其所有属性并添加到全局链表aliases_lookup上。
但是这里好像有个问题就是上面这两个属性都是通过of_find_node_by_path函数赋值的,那么of_find_node_by_path这个函数到底能不能实现上面两个节点的赋值呢,下面来看看这个函数的具体实现:

static inline struct device_node *of_find_node_by_path(const char *path)
{return of_find_node_opts_by_path(path, NULL);
}

在这里插入图片描述
从上图可以得知:of_aliases = of_find_node_by_path(“/aliases”);得到的数据应该是NULL,或者说使用of_aliases = of_find_node_by_path(“/aliases”);
这里来看个具体的aliases定义:
在这里插入图片描述

		for_each_property_of_node(of_aliases, pp) {if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {			//如上图所示这里拿到的value值就是具体的节点,这里居然再次调用了of_find_node_by_path,进行嵌套调用,这是不返回NULL不罢休np = of_find_node_by_path(pp->value);break;}}

本从日常工作中基本没有使用过of_find_node_by_path这个函数,不太清楚这个函数到底有没有问题,能不能实现具体功能。按道理所有的节点信息都会保存在of_root节点,我们直接从root节点拿节点信息就可以了。对上面有疑问的代码改写成以下实现:

	of_aliases = of_find_node_by_name(NULL, "/aliases");of_chosen = of_find_node_by_name(NULL, "/chosen");for_each_property_of_node(of_aliases, pp) {if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {			np = of_find_node_by_name(NULL,pp->value);break;}
http://www.dtcms.com/a/619586.html

相关文章:

  • 14.vector(上)
  • 烟台网站建设开发网站正在建设中永久
  • 快速搭建网站框架图互联网产品运营推广方案
  • Golang学习第一天笔记总结
  • 用jsp实现网站开发实例wordpress去除评论
  • 【Java常用API】-----System 与 标准 I/O流
  • 网站access数据库被攻击不断增大北京市建设投标网站
  • 6.HTTP协议
  • 做网站都有哪些费用网站代备案公司名称
  • 【Chrono库】Chrono DateTime 测试套件解析(src\datetime\tests.rs)
  • 佛山市网站建设哪家好龙岗网站建设哪家好
  • 青岛网站seo分析惠阳网站制作公司
  • 手机网站被禁止访问怎么设置打开怎么做广告宣传最有效
  • 如何跟客户介绍网站建设和推广网站空间位置
  • Python最佳实践:避坑web3.py,稳健gunicorn
  • “状态层同步”是什么,为什么重要,它是怎么工作的
  • 熟悉网站空间 域名等相关知识全球十大搜索引擎入口
  • 什么叫做网站整站微信营销网站(含html源文件)免费下载
  • 佛山市建设企业网站服务机构视频制作软件手机版
  • 济宁专业建网站wordpress首页添加一个超链接框
  • 建站特别慢wordpress建设一网站有什么用
  • 萝岗电子商务网站建设搜索引擎优化有哪些要点
  • 湖南it网站建设mxtia大理工程建设信息网站
  • 金仓数据库 KES:以 “五位一体” 破局,打造融合数据库标杆
  • 三门峡市住房建设局网站网络推广优化seo
  • OSPF协议配置实验报告
  • 江门企业做网站兴义做网站的公司
  • 25年11月软考架构真题《论软件系统的性能测试》考后复盘总结
  • 17zwd一起做网站广州新塘微网站分享功能
  • 高清品牌网站设计建设网站安全制度体系的建设情况