Bootloader与Kernel间参数传递机制

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


其数据结构用图形表示就是:

Bootloader与Kernel间参数传递机制_第1张图片

其实就是一个链表,通过 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 ,同时判断长度是否越界!

你可能感兴趣的:(数据结构,linux,list,struct,header,table)