目录
内核head.S对dtb的处理
1、bootloader启动内核时,会设置r0,r1,r2三个寄存器,
r0一般设置为0;
r1一般设置为machine id (在使用设备树时该参数没有被使用);
r2一般设置ATAGS或DTB的开始地址
2、machine id在kernel中的使用
3、内核hend.S的主要处理事项
a. __lookup_processor_type : 使用汇编指令读取CPU ID, 根据该ID找到对应的proc_info_list结构体(里面含有这类CPU的初始化函数、信息)
b. __vet_atags : 判断是否存在可用的ATAGS或DTB
c. __create_page_tables : 创建页表, 即创建虚拟地址和物理地址的映射关系
d. __enable_mmu : 使能MMU, 以后就要使用虚拟地址了
e. __mmap_switched : 上述函数里将会调用__mmap_switched
f. 把bootloader传入的r2参数, 保存到变量__atags_pointer中
g. 调用C函数start_kernel
head.S/head-common.S :
把bootloader传来的r1值, 赋给了C变量: __machine_arch_type
把bootloader传来的r2值, 赋给了C变量: __atags_pointer // dtb首地址
4、machine_desc结构体使用流程
(1)、在设备树dts里面的根目录指定了compatible = “samsung,smdk2440”;
(2)、当uboot将sts的首地址传递给内核后。
(3)、内核去这个地址去读取这些字符串。
(4)、然后内核在和machine_desc这个结构体里面的板卡初始化函数去比较。
(5)、如果找到相应的compatible 字符串则调用这个板卡的初始化函数。
(6)、按compatible 中的顺序找,找到后就不在找了。
5、dts中的compatible定义
6、kernel中machine_desc的定义
7、machine_desc被放到内存中的某个段中
8、kernel调用machine_desc的过程
函数调用过程:
// init/main.c
start_kernel
// arch/arm/kernel/setup.c
setup_arch(&command_line);
//分析uboot传来的dts首地址 arch/arm/kernel/devtree.c
mdesc = setup_machine_fdt(__atags_pointer);
// 判断是否有效的dtb,判断dtb的头部,drivers/of/ftd.c
early_init_dt_verify(phys_to_virt(dt_phys)
//保存dts首地址
initial_boot_params = params;
// 找到最匹配的machine_desc, drivers/of/ftd.c
mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
//一个一个的取出machine_desc来做判断
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;
}
}
machine_desc = mdesc;