atag信息处理

machine_desc->boot_params参数保存的是u-boot传入的启动参数的地址,如果没有传入启动参数,使用如下的默认参数:

/*
 * This holds our defaults.默认的tags
 */
static struct init_tags {
    struct tag_header hdr1;
    struct tag_core   core;
    struct tag_header hdr2;
    struct tag_mem32  mem;
    struct tag_header hdr3;
} init_tags __initdata = {
    
    { tag_size(tag_core), ATAG_CORE },    
    { 1, PAGE_SIZE, 0xff },
    
    { tag_size(tag_mem32), ATAG_MEM },
    { MEM_SIZE },
    { 0, ATAG_NONE }
};

内核代码通过下面的宏保存对不同的tag的处理函数,

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 }

通过__tagtable宏定义的struct tagtable都保存在特定的数据断中,

/*vmlinux.lds*/
__tagtable_begin = .;
    *(.taglist.init)
__tagtable_end = .;

常用的3个atag解析宏定义如下:

static int __init parse_tag_core(const struct tag *tag)
{
    if (tag->hdr.size > 2) {
        if ((tag->u.core.flags & 1) == 0)
            root_mountflags &= ~MS_RDONLY;
        ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
    }
    return 0;
}

__tagtable(ATAG_CORE, parse_tag_core);

static int __init parse_tag_mem32(const struct tag *tag)
{
    if (meminfo.nr_banks >= NR_BANKS) {
        printk(KERN_WARNING
               "Ignoring memory bank 0x%08x size %dKB\n",
            tag->u.mem.start, tag->u.mem.size / 1024);
        return -EINVAL;
    }
    arm_add_memory(tag->u.mem.start, tag->u.mem.size);
    return 0;
}

__tagtable(ATAG_MEM, parse_tag_mem32);

static int __init parse_tag_cmdline(const struct tag *tag)
{
    strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
    return 0;
}

__tagtable(ATAG_CMDLINE, parse_tag_cmdline);

注意,上面的defaul_command_line定义在arch/arm/kernel/setup.c中

static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;

其中CONFIG_CMDLINE在“.config”配置文件中定义的。定义如下:
CONFIG_CMDLINE="root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200 mem=64M"
default_command_line 原来的内容是我们配置文件中确定的,但是现在,被tag->u.cmdline.cmdline覆盖了。可见,从uboot传递过来的命令行参数的优先级要高于配置文件的默认命令行。

 

处理每一个tag时,使用下面的函数遍历.taglist.init段,调用相应的处理函数,

/*
 * Scan the tag table for this tag, and call its parse function.
 * The tag table is built by the linker from all the __tagtable
 * declarations.
 */
static int __init parse_tag(const struct tag *tag)
{
    extern struct tagtable __tagtable_begin, __tagtable_end;
    struct tagtable *t;

    for (t = &__tagtable_begin; t < &__tagtable_end; t++)
        if (tag->hdr.tag == t->tag) {
            t->parse(tag);
            break;
        }

    return t < &__tagtable_end;
}

 

posted @ 2017-12-25 21:19  bluebluebluesky  阅读(423)  评论(0编辑  收藏  举报