设备树(dtb数据)匹配struct machine_desc结构体
Posted 正在起飞的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设备树(dtb数据)匹配struct machine_desc结构体相关的知识,希望对你有一定的参考价值。
1、函数调用关系
start_kernel
setup_arch
setup_machine_fdt //解析dtb数据,得到匹配的struct machine_desc结构体,这是用来描述板级配置的
early_init_dt_verify //校验dtb数据
of_flat_dt_match_machine //匹配最符合的struct machine_desc结构体
get_next_compat(其实就是arch_get_next_mach) //读取编译进内核的struct machine_desc结构体的dt_compat属性
of_flat_dt_match //将struct machine_desc结构体的dt_compat属性和根节点的"compatible"属性进行匹配,匹配度越好返回的分数越小
2、struct machine_desc结构体匹配逻辑
(1)struct machine_desc结构体描述板级资源的,每块板子都有自己对应的struct machine_desc结构体,一般都是定义在mach-xxx文件中;
(2)在编译内核时,内核一般会把同架构下的mach-xxx目录都编译进去,定义的struct machine_desc结构体会被链接到一起,在链接脚本中会有标号来表示起始和结束的地址;
(3)内核启动过程中会根据起始、结束地址去遍历struct machine_desc结构体,将每个结构体的dt_compat变量和设备树根节点的compatible进行匹配,匹配度最高的struct machine_desc结构体将用于后续内核启动;
(4)如果都匹配不上会有一个默认的struct machine_desc结构体;
3、DT_MACHINE_START宏 和 MACHINE_START宏
#define MACHINE_START(_type,_name) \\
static const struct machine_desc __mach_desc_##_type \\
__used \\
__attribute__((__section__(".arch.info.init"))) = \\
.nr = MACH_TYPE_##_type, \\
.name = _name,
#define MACHINE_END \\
;
#define DT_MACHINE_START(_name, _namestr) \\
static const struct machine_desc __mach_desc_##_name \\
__used \\
__attribute__((__section__(".arch.info.init"))) = \\
.nr = ~0, \\
.name = _namestr, \\
;
(1)两个宏都是定义一个struct machine_desc变量,区别在于初始化的值不同;
(2)MACHINE_START宏是之前采用的方式,在定义时会初始化nr值,nr是机器码,用于和uboot启动内核时传递的机器码进行匹配;
(3)DT_MACHINE_START宏是设备树采用的方式,nr值在设备树中是没有使用的,在定义时nr值统一被初始化成~0。设备树是将根节点的compatible和struct machine_desc的dt_compat变量进行匹配。
4、新旧版本内核中machine_desc结构体的差异
(1)这里新旧版本的划分以设备树技术为标准,没有支持设备树的内核为旧版本,支持设备树的内核为新版本;
(2)旧版本内核中用MACHINE_START宏定义machine_desc结构体;新版本内核用DT_MACHINE_START宏定义machine_desc结构体;
(3)旧版本内核匹配machine_desc结构体是根据nr变量(机器码),和uboot启动内核时传递的机器码进行匹配;
(4)新版本内核匹配machine_desc结构体时依靠dt_compat变量,本质上是字符串,和dts文件根节点的compatible属性进行匹配;
5、arch_get_next_mach()函数
5.1、内核链接脚本
OUTPUT_ARCH(arm)
ENTRY(stext)
jiffies = jiffies_64;
SECTIONS
······
.init.arch.info :
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
······
(1)".arch.info.init"属性是用DT_MACHINE_START宏 和 MACHINE_START宏定义struct machine_desc结构体时赋予的,struct machine_desc结构体会被链接在一起;
(2)__arch_info_begin:表示内核中struct machine_desc结构体的起始地址;
(3)__arch_info_end:表示内核中struct machine_desc结构体的结束地址;
总结:所有struct machine_desc结构体会被链接在一起,类似于数组,__arch_info_begin相当于数组起始地址,__arch_info_end相当于数组的结束地址;
5.2、arch_get_next_mach()函数源码
static const void * __init arch_get_next_mach(const char *const **match)
//struct machine_desc的起始地址
static const struct machine_desc *mdesc = __arch_info_begin;
const struct machine_desc *m = mdesc;
//判断是否编译到末尾
if (m >= __arch_info_end)
return NULL;
mdesc++;
*match = m->dt_compat; //dt_compat变量是保存的字符串,用于和根节点的compatible属性进行匹配;
return m;
(1)函数会遍历内核中所有的struct machine_desc结构体,返回对应的struct machine_desc结构体指针和dt_compat变量的值;
(2)dt_compat变量的值拿去和根节点的conpatible属性进行匹配;
6、of_flat_dt_match_machine()函数
const void * __init of_flat_dt_match_machine(const void *default_match,
const void * (*get_next_compat)(const char * const**))
const void *data = NULL;
//向将最匹配的machine_desc结构体设置成默认结构体
const void *best_data = default_match;
const char *const *compat;
unsigned long dt_root;
unsigned int best_score = ~1, score = 0;
//获取dtb数据的根节点
dt_root = of_get_flat_dt_root();
//循环条件是遍历完内核中的machine_desc结构体
//其中get_next_compat函数指针就是arch_get_next_mach()函数
while ((data = get_next_compat(&compat)))
//将读取到的machine_desc结构体和根节点的compatible属性进行匹配,匹配度越高返回的score越小
score = of_flat_dt_match(dt_root, compat);
if (score > 0 && score < best_score)
best_data = data;
best_score = score;
//如果best_data是NULL则代表当前没有可用的machine_desc结构体,打印根节点的compatible属性
if (!best_data)
const char *prop;
int size;
pr_err("\\n unrecognized device tree list:\\n[ ");
prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
if (prop)
while (size > 0)
printk("'%s' ", prop);
size -= strlen(prop) + 1;
prop += strlen(prop) + 1;
printk("]\\n\\n");
return NULL;
//打印根节点的model属性值
pr_info("Machine model: %s\\n", of_flat_dt_get_machine_name());
return best_data;
(1)调用of_flat_dt_match_machine()函数会传入一个默认的machine_desc结构体,如何设备树和内核已有的machine_desc结构体没有匹配上的,则使用默认的machine_desc结构体;
(2)best_score变量是记录匹配度的,初始值是"best_score = ~1",只有匹配分数小于best_score 才会替换最匹配的machine_desc结构体,我猜测一点都不匹配soce应该是0xFFFFFFFF;
以上是关于设备树(dtb数据)匹配struct machine_desc结构体的主要内容,如果未能解决你的问题,请参考以下文章