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 ", 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; }