默认是内核boot option里面的config_cmdline,如果u-boot也传参数,则会覆盖。
u-boot传参数方法如下:
在do_bootm_linux中:
72 #ifdef CONFIG_CMDLINE_TAG
73 char *commandline = getenv ("bootargs");
74 #endif
。。。。。。。。。。。
127 #ifdef CONFIG_CMDLINE_TAG
128 setup_commandline_tag (bd, commandline);
129 #endif
在其中会将也就是bootargs的数据作为atags的一项,传递给内核:
218 params->hdr.tag = ATAG_CMDLINE;
219 params->hdr.size =
220 (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
221
222 strcpy (params->u.cmdline.cmdline, p);
内核这边则有:
699 static int __init parse_tag_cmdline(const struct tag *tag)
700 {
701 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
702 return 0;
703 }
704
705 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
通过__tagtable,parse_tag_cmdline将在初始化中被调用,如果存在u-boot传来的bootargs,则覆盖掉内核原有的config_cmdline。default_command_line会由原始编译内核时的config_cmdline变为bootargs。
继续内核会去分析command,在setup_arch中,
771 char *from = default_command_line;
。。。。
806 memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
807 saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
808 parse_cmdline(cmdline_p, from);
可以看出随后内核将这个改变后的值进行parse,并且根据parse的结果做相应的设置。
比如首先分析内存:
809 paging_init(&meminfo, mdesc);
包括页表,内存区域等设置。剩下的cmdline会交由后面分析,setup_arch返回后,start_kernel执行到
530 parse_args("Booting kernel", command_line, __start___param,
531 __stop___param - __start___param,
532 &unknown_bootoption);
就会调用parse_args对剩下的cmdline进行解析。
可以看出,对于cmdline的处理是以uboot为优先,但是如果将parse_tag_cmdline函数中的内容注释掉,则起作用的就是内核了。
附带额外说一些对内存的设置。cmdline里面有类似mem=xxx这样的设置,但初次以外,内核还必须知道ram的起始地址,因为不像x86,固定从0开始,而且每款arm的soc,内存地址映射都不一样,所以内核必须知道物理地址起址是多少。
首先u-boot中会通过init_sequence指针去设置dram:
5 init_fnc_t *init_sequence[] = {
。。。
298 dram_init, /* configure available RAM banks */
。。。
301 };
dram设置内存大小和起始地址:
268 int dram_init(void)
269 {
270 gd->bd->bi_dram[0].start = PHYS_SDRAM;
271 gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE;
272 return 0;
273 }
PHYS_SDRAM和PHYS_SDRAM_SIZE都定义在各自的include/configs/xxx.h里面
在do_bootm_linux里面,有:
124 #ifdef CONFIG_SETUP_MEMORY_TAGS
125 setup_memory_tags (bd);
126 #endif
就是设置atags的内存区域的值:
static void setup_memory_tags (bd_t *bd)
186 {
187 int i;
188
189 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
190 params->hdr.tag = ATAG_MEM;
191 params->hdr.size = tag_size (tag_mem32);
192
193 params->u.mem.start = bd->bi_dram[i].start;
194 params->u.mem.size = bd->bi_dram[i].size;
195
196 params = tag_next (params);
197 }
198 }
类似parse_tag_cmdline,会有:
611 static int __init parse_tag_mem32(const struct tag *tag)
612 {
613 if (meminfo.nr_banks >= NR_BANKS) {
614 printk(KERN_WARNING
615 "Ignoring memory bank 0x%08x size %dKB\n",
616 tag->u.mem.start, tag->u.mem.size / 1024);
617 return -EINVAL;
618 }
619 arm_add_memory(tag->u.mem.start, tag->u.mem.size);
620 return 0;
621 }
622
623 __tagtable(ATAG_MEM, parse_tag_mem32);
但是注意,并不是你传了这个atag,他就会起作用,在setup_arch中有:
792 if (mdesc->fixup)
793 mdesc->fixup(mdesc, tags, &from, &meminfo);
这个fixup函数是板级相关的,通常就是一些ram起址大小bank之类的设定函数,如果执行过了,nrbank就不为0了,那么继续执行后面的语句时:
795 if (tags->hdr.tag == ATAG_CORE) {
796 if (meminfo.nr_banks != 0)
797 squash_mem_tags(tags);
798 parse_tags(tags);
799 }
就会调用squash_mem_tags把你u-boot传入的值给干掉,使parse_tags函数调用时不会处理ATAG_MEM。
参考链接:
1.http://blog.chinaunix.net/u1/46715/showart_367493.html
2.http://blog.youkuaiyun.com/cooboos/archive/2010/05/07/5567142.aspx
u-boot 内核同时传递cmdline时的处理
最新推荐文章于 2024-09-21 10:34:24 发布