machid
在没有设备树的时候,machine相关的初始化函数都在类似arch/arm/mach-s3c24xx的目录下。
图中圈住的machine,他们都属于arm/mach-s3c24xx体系,在内核配置s3c24xx时,都会被编进内核。
U-boot传入machid到内核用到的是param_struct/tag,内核根据U-boot传入的machid选择不同的初始化函数。
在include/generated/mach-types.h下可以看到很多单板对应的machid。
内核解析machid
箭头上面那行mdesc = setup_machine_fdt(__atags_pointer);是解析设备树的,而setup_machine_tags函数就是解析U-boot传入的tag(machid)。
for_each_machine_desc(p)是宏。
/*
* Machine type table - also only accessible during boot
*/
extern struct machine_desc __arch_info_begin[], __arch_info_end[];
#define for_each_machine_desc(p) \
for (p = __arch_info_begin; p < __arch_info_end; p++)
__arch_info_begin到__arch_info_end存储的就是machine_desc结构体,遍历其中的machine_desc,当某一machine_desc的nr和machine_nr(U-boot传入)相等时break。
__arch_info_begin、__arch_info_end、nr
把machine_desc结构体放入指定位置就是利用了编译器的特性。
http://blog.csdn.net/qq_33160790/article/details/79256279
打开arch/arm/mach-s3c24xx/mach-smdk2440.c文件,末尾可以看到上面部分。
/*
* Set of macros to define architecture features. This is built into
* a table by the linker.
*/
#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 \
};
这里attribute((section(“.arch.info.init”)))就是利用了编译器的特性,把machine_desc放到了.arch.info.init段。
.init.arch.info : {
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
}
vmlinux.lds链接文件中可以看到.arch.info.init的起始和结束就是__arch_info_begin、__arch_info_end。
回到前面的MACHINE_START(_type,_name)宏,_type是S3C2440。经过##连接
.nr = MACH_TYPE_##_type就变为:
.nr = MACH_TYPE_S3C2440,联系到前面提到的mach-types.h。
这里nr就等于362(十六进制的16a)。
贴上machine_desc结构体。