__unflatten_device_tree
来源:互联网 发布:html与css javascript 编辑:程序博客网 时间:2024/06/15 17:07
void __unflatten_device_tree(struct boot_param_header blob,struct device_node **mynodes,void (*dt_alloc)(u64 size, u64 align))
1.解析设备树头信息
2.计算设备节点的个数,根据个数来为设备节点分配内存
3.从设备树上将设备节点解析出来
4.解析完成后,校验一下解析的结果
mem:从ram分配的起始地址,也就是of_allnodes 指针指向的地址
np:设备节点地址
pp:属性地址
ap:别名地址
主要执行的函数是:
unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
其中,blob:设备树头信息指针(initial_boot_params)。mem:设备节点分配的空间地址start:设备树信息开始的地方,allnextp:指向设备节点头(of_allnodes)。
/**
* unflatten_dt_node - Alloc and populate a device_node from the flat tree
* @blob: The parent device tree blob
* @mem: Memory chunk to use for allocating device nodes and properties
* @p: pointer to node in flat tree
* @dad: Parent struct device_node
* @allnextpp: pointer to ->allnext from last allocated device_node
* @fpsize: Size of the node path up at the current depth.
*/
unsigned long unflatten_dt_node(struct boot_param_header *blob,unsigned long mem,unsigned long *p,struct device_node *dad,struct device_node ***allnextpp,unsigned long fpsize)
{
struct device_node *np;
struct property *pp, **prev_pp = NULL;
char *pathp;
u32 tag;
unsigned int l, allocl;
int has_name = 0;
int new_format = 0;
tag = be32_to_cpup((__be32 *)(*p)); //每个有孩子的设备节点,其tag一定是OF_DT_BEGIN_NODEif (tag != OF_DT_BEGIN_NODE) { pr_err("Weird tag at start of node: %x\n", tag); return mem;}*p += 4; //地址+4,这样指向节点的名称pathp = (char *)*p;l = allocl = strlen(pathp) + 1; //该节点名称的长度*p = ALIGN(*p + l, 4); ///*p 指向带分析的属性/* version 0x10 has a more compact unit name here instead of the full * path. we accumulate the full path size using "fpsize", we'll rebuild * it later. We detect this because the first character of the name is * not '/'. */ /*计算fullpath的长度 */if ((*pathp) != '/') { new_format = 1; if (fpsize == 0) { //根节点 /* root node: special case. fpsize accounts for path * plus terminating zero. root node only has '/', so * fpsize should be 2, but we want to avoid the first * level nodes to have two '/' so we use fpsize 1 here */ fpsize = 1; allocl = 2; //要分配的长度 } else { /* account for '/' and path size minus terminal 0 * already in 'l' */ fpsize += l; //要分配的长度=本节点名称长度+父亲节点绝对路径的长度 allocl = fpsize; }}/* 分配一个设备节点 *///mem = 0 , np就是分配的 struct device node 大小的内存的指针np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, __alignof__(struct device_node));//下面是判断,填充np,构造出device node/* allnextpp指向前一个设备链表的指针 */if (allnextpp) { //第二次扫描 nextpp 存在要进入 if 内执行 memset(np, 0, sizeof(*np)); np->full_name = ((char *)np) + sizeof(struct device_node); if (new_format) { char *fn = np->full_name; /* rebuild full path for new format */ if (dad && dad->parent) { strcpy(fn, dad->full_name); //把父亲节点绝对路径先拷贝
ifdef DEBUG
if ((strlen(fn) + l + 1) != allocl) { pr_debug("%s: p: %d, l: %d, a: %d\n", pathp, (int)strlen(fn), l, allocl); }
endif
fn += strlen(fn); } *(fn++) = '/'; memcpy(fn, pathp, l); //拷贝本节点的名称 } else memcpy(np->full_name, pathp, l); prev_pp = &np->properties; //prev_pp指向节点的属性 **allnextpp = np; //当前节点插入链表 *allnextpp = &np->allnext; if (dad != NULL) { //父亲节点不为空 np->parent = dad; //指向父亲节点 /* we temporarily use the next field as `last_child'*/ if (dad->next == NULL) //第一个孩子 dad->child = np; //child指向第一个孩子 else dad->next->sibling = np; //把np插入next,这样孩子节点形成链表 dad->next = np; //指向最新挂接的child node } kref_init(&np->kref);}/* process properties *//*分析设备的属性*/while (1) { u32 sz, noff; char *pname; tag = be32_to_cpup((__be32 *)(*p)); if (tag == OF_DT_NOP) { //空属性,则跳过 *p += 4; continue; } /* tag不是属性则退出,对于有孩子节点退出时为OF_DT_BEGIN_NODE; * 对于叶子节点退出时为OF_DT_END_NODE. */ if (tag != OF_DT_PROP) break; *p += 4; //地址加4 sz = be32_to_cpup((__be32 *)(*p)); //属性的大小,是以为占多少整形指针计算的。例如网卡interrupts = <35 2 36 2 40 2>;,其值为24 noff = be32_to_cpup((__be32 *)((*p) + 4)); *p += 8; //指向value if (be32_to_cpu(blob->version) < 0x10) *p = ALIGN(*p, sz >= 8 ? 8 : 4); pname = of_fdt_get_string(blob, noff); //属性名称 if (pname == NULL) { pr_info("Can't find property name in list !\n"); break; } if (strcmp(pname, "name") == 0) //如果有名称为name的属性 has_name = 1; l = strlen(pname) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property), __alignof__(struct property)); //分配属性结构 if (allnextpp) { /* We accept flattened tree phandles either in * ePAPR-style "phandle" properties, or the * legacy "linux,phandle" properties. If both * appear and have different values, things * will get weird. Don't do that. */ if ((strcmp(pname, "phandle") == 0) || (strcmp(pname, "linux,phandle") == 0)) { if (np->phandle == 0) np->phandle = be32_to_cpup((__be32*)*p); } /* And we process the "ibm,phandle" property * used in pSeries dynamic device tree * stuff */ if (strcmp(pname, "ibm,phandle") == 0) np->phandle = be32_to_cpup((__be32 *)*p); pp->name = pname; //属性名 pp->length = sz; //长度 pp->value = (void *)*p; //属性值 *prev_pp = pp; //属性插入属性链表 prev_pp = &pp->next; } *p = ALIGN((*p) + sz, 4); //指向下一个属性}/* with version 0x10 we may not have the name property, recreate * it here from the unit name if absent */if (!has_name) { //如果没有name,就创建一个 char *p1 = pathp, *ps = pathp, *pa = NULL; int sz; while (*p1) { if ((*p1) == '@') pa = p1; if ((*p1) == '/') ps = p1 + 1; p1++; } if (pa < ps) pa = p1; sz = (pa - ps) + 1; pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, __alignof__(struct property)); if (allnextpp) { pp->name = "name"; pp->length = sz; pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); //名字的值只去其中的@钱的字符,例如pcie@ffe0a000-> pcie ((char *)pp->value)[sz - 1] = 0; pr_debug("fixed up name for %s -> %s\n", pathp, (char *)pp->value); }}if (allnextpp) { //如果有属性链表 *prev_pp = NULL; np->name = of_get_property(np, "name", NULL); //设置节点的名称 np->type = of_get_property(np, "device_type", NULL);//设置设备类型 if (!np->name) np->name = "<NULL>"; if (!np->type) np->type = "<NULL>";}while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {//对于tag为这2个取值 if (tag == OF_DT_NOP) //空属性则指向下个属性 *p += 4; else mem = unflatten_dt_node(blob, mem, p, np, allnextpp, fpsize); //OF_DT_BEGIN_NODE则表明其还有子节点,所以递归分析其子节点 tag = be32_to_cpup((__be32 *)(*p));}if (tag != OF_DT_END_NODE) { //对于叶子节点或者分析完成 pr_err("Weird tag at end of node: %x\n", tag); return mem;}*p += 4;return mem;
}
设备树中的cpu 设备
enable-method ,通过这个名称,找到cpu.ops,也就是smp_spin_table_ops
- __unflatten_device_tree
- Java容器(一)之Iterator与Iterable接口
- 【转】jvm系列(一):java类的加载机制
- nginx比apache快的原因
- LeetCode:Reverse Vowels of a String
- 来到博客的第一天
- __unflatten_device_tree
- bzoj1131 [POI2008]Sta 树形DP
- javaweb第二章2.1.5
- SecureCRT 8.1安装与激活
- linux .tar.gz文件 解压缩命令简单使用
- 软件测试面试题
- 面向对象六大设计原则(一)单一职责原则
- Python中列表常用的操作符
- 统计字符串字母,数字,空格和其他字符个数