Linux 内核如何根据设备树文件来匹配内核

一.  简介

上一篇文章学习了 Linux内核如何确定是否支持此设备,如果支持,设备就会启动 Linux 内核。

文章地址如下:

设备树根节点下的compatile属性的作用-CSDN博客

本文继上面文章的学习。这里简单看一下, Linux 内核是如何根据设备树根节点的 compatible 属性来匹配出对 应的 machine_desc。

二.    Linux 内核如何根据设备树根节点的 compatible 属性来匹配machine_desc

Linux 内核调用 start_kernel 函数来启动内核, start_kernel 函数会调用 setup_arch 函数来匹配 machine_desc setup_arch 函数定义在文件 arch/arm/kernel/setup.c 中,函 数内容如下 ( 有缩减 )
void __init setup_arch(char **cmdline_p)
{
	const struct machine_desc *mdesc;

	setup_processor();
	mdesc = setup_machine_fdt(__atags_pointer);
	if (!mdesc)
		mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
	machine_desc = mdesc;
	machine_name = mdesc->name;
...............
}
6 行,调用 setup_machine_fdt() 函数来获取匹配的 machine_desc ,参数就是 atags 的首 地址,也就是 uboot 传递给 Linux 内核的 . dtb 设备树 文件的首地址, setup_machine_fdt() 函数的返回值就是 找到的最匹配的 machine_desc

函数 setup_machine_fdt 定义在文件 arch/arm/kernel/devtree.c 中,内容如下(有缩减)

const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
{
     const struct machine_desc *mdesc, *mdesc_best = NULL;
......

     if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))
         return NULL;

     mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
......
     __machine_arch_type = mdesc->nr;

     return mdesc;
}

8 行,调用函数 of_flat_dt_match_machine()函数 来获取匹配的 machine_desc ,参数 mdesc_best 是 默 认 的 machine_desc
参数 arch_get_next_mach 是 个 函 数 , 此 函 数 定 义 在 定 义 在 arch/arm/kernel/devtree.c 文件中。
找到匹配的 machine_desc 的过程,就是用设备树根节点的 compatible 属性值和 Linux 内核中 machine_desc .dt_compat 的值比较,看看那个相等,如果相 等,就表示找到匹配的 machine_desc arch_get_next_mach 函数的工作就是获取 Linux 内核中 下一个 machine_desc 结构体。

最后再来看一下 of_flat_dt_match_machine 函数,此函数定义在文件 drivers/of/fdt.c 中,内容如下(有缩减)

const void * __init of_flat_dt_match_machine(const void *default_match,
		const void * (*get_next_compat)(const char * const**))
{
	const void *data = NULL;
	const void *best_data = default_match;
	const char *const *compat;
	unsigned long dt_root;
	unsigned int best_score = ~1, score = 0;

	dt_root = of_get_flat_dt_root();
	while ((data = get_next_compat(&compat))) {
		score = of_flat_dt_match(dt_root, compat);
		if (score > 0 && score < best_score) {
			best_data = data;
			best_score = score;
		}
	}
........................

	pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());

	return best_data;
}

第 10 行,通过 of_get_flat_dt_root() 函数获取设备树根节点。
11~16 行,此循环就是查找匹配的 machine_desc 过程。
12 行的 of_flat_dt_match 数,会将根节点 compatible 属性的值和每个 machine_desc 结构体中 . dt_compat 的值进行比较,直 至找到匹配的那个 machine_desc

三.  总结

总结一下, Linux 内核通过根节点 compatible 属性找到对应的设备的函数调用过程。过程 如下图所示:
Linux 内核如何根据设备树文件来匹配内核_第1张图片

你可能感兴趣的:(Linux驱动学习,linux,arm开发)