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
,同时判断长度是否越界!