由于工作需求,不得不看内核源码。有关于dts 的相关解析知识跟大家分享下,这块也是博主看了好长时间的源码才串起来了。做个博客记录下,顺便复习一遍,也对有需要的人是个参考。
关于dts我就不详解介绍了,网上博客一大堆。我们知道在内核启动的过程中,由于dts的加入,我们先是将dts解析成树型结构,然后放在内存中,等待内核后面注册devices和driver的时候再来铺开调用。
那么dts是在哪块被解析的呢?又是怎么进行解析的呢。内核的启动是在start_kernel()函数中进行启动的,在start_kernel()函数中调用了 setup_arch(&command_line) 架构相关的函数。因为我们分析的是64位的系统,所以 setup_arch()在 arch/arm64/kernel/setup.c 中。我们进入到这个函数中,涉及到dts的有三个函数,分别是 setup_machine_fdt(__fdt_pointer); arm64_memblock_init(); unflatten_device_tree(); 接下来我们就分别分析下这三个函数,在他们里面是怎样进行dts的创建及解析的。
A、首先是 setup_machine_fdt(),我们进到函数里,它位于 arch/arm64/kernel/setup.c 中。函数源码如下static void __init setup_machine_fdt(phys_addr_t dt_phys)
{
void *dt_virt = fixmap_remap_fdt(dt_phys);
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
pr_crit("\n"
"Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n"
"The dtb must be 8-byte aligned and must not exceed 2 MB in size\n"
"\nPlease check your bootloader.",
&dt_phys, dt_virt);
while (true)
cpu_relax();
}
dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
}
在这个函数中,我们再追进去看看 fixmap_remap_fdt() 和 early_init_dt_scan()。
fixmap_remap_fdt()源码如下void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
{
void *dt_virt;
int size;
dt_virt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO);
if (!dt_virt)
return NULL;
memblock_reserve(dt_phys, size);
return dt_virt;
}
我们可以看出这个函数是为fdt建立地址映射,在该函数的最后,顺便就调用memblock_reserve 保留了该段内存
early_init_dt_scan() 源码如下bool __init early_init_dt_scan(void *params)
{
bool status;
status = early_init_dt_verify(params);
if (!status)
return false;
early_init_dt_scan_nodes();
return true;
}
我们可以看出在这个函数里又调用了 early_init_dt_verify(params) 和 early_init_dt_scan_nodes()函数,再追进去看看这两个函数分别实现了什么
early_init_dt_verify(params) 源码如下bool __init early_init_dt_verify(void *params)
{
if (!params)
return false;
/* check device tree validity */
if