考试首页 | 考试用书 | 培训课程 | 模拟考场 | 考试论坛  
  当前位置:操作系统 > Linux > 文章内容
  

Linux基础教程:Linux设备树(Devicetree)

 [ 2016年2月18日 ] 【

of_flat_dt_match_machine的其余部分代码都是出错处理及打印,现在我们看of_flat_dt_match的实现,该函数仅仅是直接调用of_fdt_match而已,不同的是增加了initial_boot_params参数(还记得我们说过前边说过的这个变量的初始化吧,其实这就是内核中的一个简单封装而已)。

 685 /**
 686  * of_flat_dt_match - Return true if node matches a list of compatible values
 687  */
 688 int __init of_flat_dt_match(unsigned long node, const char *const *compat)
 689 { 
 690    return of_fdt_match(initial_boot_params, node, compat);
 691 } 

of_fdt_match函数从142行开始遍历compat数组的每一个字符串,然后通过of_fdt_is_compatible函数计算匹配度(以最小的数值作为最终的结果)。代码到这个地方已经很好理解了,compat中的数据来自内核的.arch.info.init段,这个段表示内核支持的平台,blob是设备树其实地址,通过node节点指定根节点的compatible属性,然后计算匹配度。还记得我们前边说过的 compatible属性包含多个字符串,从前向后范围越来越大,优先匹配前边的,这个地方代码计算分数(score变量)就是这个目的。
 131 /**
 132  * of_fdt_match - Return true if node matches a list of compatible values
 133  */
 134 int of_fdt_match(const void *blob, unsigned long node,
 135                  const char *const *compat)
 136 {
 137    unsigned int tmp, score = 0;
 138
 139    if (!compat)
 140        return 0;
 141
 142    while (*compat) {
 143        tmp = of_fdt_is_compatible(blob, node, *compat);
 144        if (tmp && (score == 0 || (tmp < score)))
 145            score = tmp;
 146        compat++;
 147    }
 148
 149    return score;
 150 }

继续看of_fdt_is_compatible函数的实现,第97行已经看到找该节点下的"compatible"属性了。

  80 /**
  81  * of_fdt_is_compatible - Return true if given node from the given blob has
  82  * compat in its compatible list
  83  * @blob: A device tree blob
  84  * @node: node to test
  85  * @compat: compatible string to compare with compatible list.
  86  *
  87  * On match, returns a non-zero value with smaller values returned for more
  88  * specific compatible values.
  89  */
  90 int of_fdt_is_compatible(const void *blob,
  91              unsigned long node, const char *compat)
  92 {
  93    const char *cp;
  94    int cplen;
  95    unsigned long l, score = 0;
  96
  97    cp = fdt_getprop(blob, node, "compatible", &cplen);
  98    if (cp == NULL)
  99        return 0;
 100    while (cplen > 0) {
 101        score++;
 102        if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
 103            return score;
 104        l = strlen(cp) + 1;
 105        cp += l;
 106        cplen -= l;
 107    }
 108
 109    return 0;
 110 }

关于根节点的"compatible"属性我们就说到这,一句话总结下就是内核通过"compatible"属性找到对应的平台描述信息,按照范围从小到大尽量匹配范围最小的,如果匹配不到,那么说明内核不支持该平台,系统将在初始化的时候就出错。

根节点还可能包含的属性为#address-cells和#size-cells,规范中说明这两个属性是必须的,实际应用时是可选的,还记得属性那一节说这两个属性如果没有都是有默认值的,#address-cells默认值为2,#size-cells默认值为1。根节点下必须包含的子节点为 cpus和memory,后边会说明cpus下边还有每个cpu的子节点,memory节点下边定义的就是memory的起始地址及大小,所以根节点的#address-cells和#size-cells属性实际上说明的就是从cpu角度看系统总线的地址长度和大小。

规范中还写根节点下边必须有一个epapr-version属性用来描述设备树的版本,实际上在linux中根本不用这个属性。

本文纠错】【告诉好友】【打印此文】【返回顶部
将考试网添加到收藏夹 | 每次上网自动访问考试网 | 复制本页地址,传给QQ/MSN上的好友 | 申请链接 | 意见留言 TOP
关于本站  网站声明  广告服务  联系方式  站内导航  考试论坛
Copyright © 2007-2013 中华考试网(Examw.com) All Rights Reserved