boot_linux_from_mmc
|-> dt_table_offset=((uint32_t)image_addr+page_size+kernel_actual_ramdisk_actual+second_actual); ------------------------------找到dts的偏移地址
|->table = (structdt_table*) dt_table_offset; ----------------------------------找到dts的地址
|->dev_tree_get_entry_into(table ,&dt_entry) ----------------------------------进入匹配接口函数
|->target_variant_id = board_target_id() -----------------------------------获取board.platform对应的platform id
|->__dev_tree_get_entry_info(table,dt_entry_info,target_variant_id,0xff) -----------------------------------获取dts里面的platform id与board.platform对应的platform id
|->table_ptr=(unsigned char*)table + DEV_TREE_HEADER_SIZE
|->dt_entry_v1=(structdt_entry_v1 *)table_ptr
|->platform_dt_match(cur_dt_entry, target_variant_id, subtype_mask)
|->if(fond != 0) -----------------------------------如果找到,匹配成功
Kmain()---------------------------------------------汇编进入lk的第一个函数
|->platform_early_init();
|->board_init();
|->platform_detect()
|->board.platform =board_info_v8.board_info_v3.msm_id;
进入kernel之后进入下面流程
//---------------------------------------------kernel/arch/arm/mach-msm/board-8916.c
DT_MACHINE_START(MSM8916_DT,
"Qualcomm Technologies,Inc. MSM 8916 (Flattened Device Tree)")
.map_io = msm8916_map_io,
.init_machine = msm8916_init,
.dt_compat = msm8916_dt_match,
.reserve = msm8916_dt_reserve,
.init_very_early =msm8916_early_memory,
.smp = &msm8916_smp_ops,
MACHINE_END
static const char *msm8916_dt_match[]__initconst = {
"qcom,msm8916",
"qcom,apq8016",
NULL
};
#define DT_MACHINE_START(_name,_namestr) \
static const structmachine_desc __mach_desc_##_name \
__used \
__attribute__((__section__(".arch.info.init")))= { \
.nr = ~0, \
.name = _namestr,
这些不同的machine会有不同的MACHINEID,Uboot在启动Linux内核时会将MACHINE ID存放在r1寄存器,Linux启动时会匹配Bootloader传递的MACHINE ID和
MACHINE_START声明的MACHINEID,然后执行相应machine的一系列初始化函数。
引入Device Tree之后,MACHINE_START变更为DT_MACHINE_START,其中含有一个.dt_compat成员,用于表明相关的machine与.dts中root结点的compatible属性兼容关系。如果Bootloader传递给内核的DeviceTree中root结点的compatible属性出现在某machine的.dt_compat表中,相关的machine就与对应的Device Tree匹配,从而引发这一machine的一系列初始化函数被执行。
这个类型的变量放在内核代码段.arch.info.init中,在内核运行初期,被函数lookup_machine_type(此函数用汇编实现,在汇编文件中)取出,读取流程为
Start_kernel()-> setup_arch() -> setup_machine() -> lookup_machine_type()