u-boot 核心同時傳遞cmdline時的處理
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.csdn.net/cooboos/archive/2010/05/07/5567142.aspx