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,同时判断长度是否越界!
阅读(1120) | 评论(0) | 转发(0) |