Chinaunix首页 | 论坛 | 博客
  • 博客访问: 465033
  • 博文数量: 63
  • 博客积分: 1485
  • 博客等级: 上尉
  • 技术积分: 596
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-21 14:49
文章分类

全部博文(63)

文章存档

2018年(8)

2017年(25)

2016年(10)

2012年(6)

2010年(14)

我的朋友

分类: LINUX

2010-03-03 17:33:53

 本文原创,转贴请注明出处,谢谢!
 本文分析对象: arm linux 2.6.29


Tag list被用来在bootloaderlinux kernel 之间传递参数,这里分析一下相关的数据结构,主要包括两个部分:Tag list Tag parser list

先来看Tag list

这个list是在bootloader中填充的,其数据结构定义在bootloaderlinux 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,同时判断长度是否越界!

阅读(3341) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~