Tag list被用来在bootloader和linux kernel 之间传递参数,这里分析一下相关的数据结构,主要包括两个部分:Tag list 和Tag parser list。
先来看Tag list:
这个list是在bootloader中填充的,其数据结构定义在bootloader和linux kernel中均有定义,是一致的。我们来看linux kernel中的定义:
top/arch/arm/include/asm/setup.h
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_videotext videotext;
struct tag_ramdisk ramdisk;
struct tag_initrd initrd;
struct tag_serialnr serialnr;
struct tag_revision revision;
struct tag_videolfb videolfb;
struct tag_cmdline cmdline;
/*
* Acorn specific
*/
struct tag_acorn acorn;
/*
* DC21285 specific
*/
struct tag_memclk memclk;
} u;
};
struct tag_header {
__u32 size;
__u32 tag;
};
|
其中tag的取值如下,暂且称之为tag
type:
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_VIDEOTEXT 0x54410003
#define ATAG_RAMDISK 0x54410004
#define ATAG_INITRD 0x54410005
#define ATAG_INITRD2 0x54420005
#define ATAG_SERIAL 0x54410006
#define ATAG_REVISION 0x54410007
#define ATAG_VIDEOLFB 0x54410008
#define ATAG_CMDLINE 0x54410009
#define ATAG_ACORN 0x41000101
#define ATAG_MEMCLK 0x41000402
|
其数据结构用图形表示就是:
其实就是一个链表,通过Tag
size以及当前tag的位置来定位下一个tag的位置。而且第一个tag的类型必然是ATAG_CORE。
参数就是按照这个结构进行传递的,那么kernel是如何进行解析的呢?
我们来看tag parser
list:
同样是在top/arch/arm/include/asm/setup.h,有如下定义:
top/arch/arm/include/asm/setup.h struct tagtable {
__u32 tag;
int (*parse)(const struct tag *);
};
#define __tag __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn) \
static struct tagtable __tagtable_##fn __tag = { tag, fn }
|
从上面知道,tag parser list存在于.taglist.init段,他们的定义将通过宏__tagtable(tag, fn)的形式给出,比如在 top/arch/arm/kernel/setup.c中:top/arch/arm/kernel/setup.c __tagtable(ATAG_CORE, parse_tag_core);
__tagtable(ATAG_MEM, parse_tag_mem32);
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
__tagtable(ATAG_SERIAL, parse_tag_serialnr);
__tagtable(ATAG_REVISION, parse_tag_revision);
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
|
通过这样的定义,每个tag table的表项就自动连接在了一起,而且存在于同一个段中。如图所示:
可以看到,所有支持的tag parser都列在这里了。
在kernel中,将针对tag
list中的每一项在这个tag parser list中进行查找,如果有对应的处理项,则调用解析函数,于是就完成了参数的传递以及解析!
注意:
在top/arch/arm/kernel/head-common.s中会对从bootloader传递过来的tag list进行合法性判断:
以标号__vet_atags开始的一段处理就要是判断tag list的第一项是否是ATAG_CORE,同时判断长度是否越界!
阅读(1194) | 评论(0) | 转发(0) |