u-boot向linux内核传递启动参数
? ?? 例如u-boot-1.3.4在arm平臺(tái)下,該函數(shù)的實(shí)現(xiàn)位于:lib_arm\Bootm.c文件中.
???在文件中有如下代碼:(可以參照《完全手冊(cè)》的244頁(yè))
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
??? defined(CONFIG_CMDLINE_TAG) || \
??? defined(CONFIG_INITRD_TAG) || \
??? defined(CONFIG_SERIAL_TAG) || \
??? defined(CONFIG_REVISION_TAG) || \
??? defined(CONFIG_LCD) || \
??? defined(CONFIG_VFD)
static void setup_start_tag (bd_t *bd)
{
??? params =(struct tag *) bd->bi_boot_params;
???params->hdr.tag = ATAG_CORE;
???params->hdr.size = tag_size (tag_core);
???params->u.core.flags = 0;
???params->u.core.pagesize = 0;
???params->u.core.rootdev = 0;
??? params =tag_next (params);
}
???上面是初始化tag鏈表(在SDRAM里),最后一句是作為鏈表的最關(guān)鍵部分,它的定義是:
#definetag_next(t)???((struct tag *)((u32 *)(t) +(t)->hdr.size))?作用是指向下一個(gè)tag結(jié)構(gòu)體。 其中 defined (CONFIG_SETUP_MEMORY_TAGS) 和defined (CONFIG_CMDLINE_TAG)是必不可少的。前者是標(biāo)記內(nèi)存的信息,而后者是設(shè)置命令行標(biāo)記(比如“root=/dev/mtdblock2init=/linuxrc console=ttySAC0”)
????/common/cmd_bootm.c文件中, bootm 命令對(duì)應(yīng)的do_bootm函數(shù),當(dāng)分析 uImage 中信息發(fā)現(xiàn) OS 是 Linux 時(shí) ,調(diào)用./lib_arm/bootm.c文件中的 do_bootm_linux函數(shù)來(lái)啟動(dòng) Linuxkernel 。
??????在 do_bootm_linux函數(shù)中:
voiddo_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char*argv[],
?????????????????ulong addr, ulong *len_ptr, int verify)
{
......
#if defined(CONFIG_SETUP_MEMORY_TAGS) || \
???defined (CONFIG_CMDLINE_TAG) || \
???defined (CONFIG_INITRD_TAG) || \
???defined (CONFIG_SERIAL_TAG) || \
???defined (CONFIG_REVISION_TAG) || \
???defined (CONFIG_LCD) || \
???defined (CONFIG_VFD)
??????setup_start_tag(bd);?????// 初始化tag 結(jié)構(gòu)體開(kāi)始
#ifdefCONFIG_SERIAL_TAG
??????setup_serial_tag(¶ms);
#endif
#ifdefCONFIG_REVISION_TAG
??????setup_revision_tag(¶ms);
#endif
#ifdefCONFIG_SETUP_MEMORY_TAGS
??????setup_memory_tags(bd);?????// 設(shè)置 RAM 參數(shù)
#endif
#ifdefCONFIG_CMDLINE_TAG
??????setup_commandline_tag (bd, commandline);
#endif
#ifdefCONFIG_INITRD_TAG
??????if (initrd_start &&initrd_end)
?????????????setup_initrd_tag (bd, initrd_start,initrd_end);
#endif
#if defined(CONFIG_VFD) || defined (CONFIG_LCD)
??????setup_videolfb_tag ((gd_t *) gd);
#endif
??????setup_end_tag(bd);?????????????// 初始化tag 結(jié)構(gòu)體結(jié)束
#endif
......
......
??????theKernel (0, machid,bd->bi_boot_params);
// 傳給 Kernel 的參數(shù)=(struct tag*) 型的 bd->bi_boot_params
當(dāng)然,有很多的宏來(lái)選擇是否傳遞相應(yīng)的tag到linuxkenel.實(shí)際是這些所以針對(duì)于 bd->bi_boot_params這個(gè)變量.這個(gè)變量是個(gè)整形變量,代表存放所有tag的buffer的地址.例如,在 smdk2410.c 中的 board_init() 函數(shù)中,對(duì)于這個(gè)變量進(jìn)行了如下賦值:
???
???gd->bd->bi_boot_params = 0x30000100;
0x30000100這個(gè)值可以隨意指定, 但是要保證和內(nèi)核中相應(yīng)的mach_type 一致.以smdk2410為例:
在內(nèi)核中始終這個(gè)值的地方是: arch\arm\mach-s3c2410\mach-smdk2410.c的最后
MACHINE_START(SMDK2410, "SMDK2410")
???
???.phys_ram??? =S3C2410_SDRAM_PA,
???.phys_io??? =S3C2410_PA_UART,
???.io_pg_offst???= (((u32)S3C24XX_VA_UART) >> 18)& 0xfffc,
??? .boot_params???= S3C2410_SDRAM_PA + 0x100,
???.map_io?????? =smdk2410_map_io,
???.init_irq??? =smdk2410_init_irq,
???.timer?????? =&s3c24xx_timer,
MACHINE_END
紅色部分的值, 必須等于0x30000100, 否者將會(huì)出現(xiàn)無(wú)法啟動(dòng)的問(wèn)題.
內(nèi)核啟動(dòng)后,會(huì)讀取0x300000100位置的值, 當(dāng)然,內(nèi)核會(huì)把這個(gè)地址轉(zhuǎn)換成邏輯地址在操作. 因?yàn)閮?nèi)核跑起來(lái)后,MMU已經(jīng)工作,必須要把0x300000100這個(gè)物理地址轉(zhuǎn)成邏輯地址然后在操作.
對(duì)于u- boot傳給內(nèi)核的參數(shù)中(tag), 內(nèi)核比較關(guān)系memory的信息,比如memory地址的起始,大小等.
如果沒(méi)有得到,那么內(nèi)核無(wú)法啟 動(dòng),內(nèi)核會(huì)進(jìn)入BUG()函數(shù),然后死在那里.
而memory的信息是由CONFIG_SETUP_MEMORY_TAGS宏決定的. 因此當(dāng)這個(gè)宏沒(méi)有被定義時(shí),內(nèi)核跑不起來(lái). 初始化meminfo時(shí)會(huì)失敗.現(xiàn)象就是:?
Starting Kernel ...
死掉.
一般需要定義:
#defineCONFIG_SETUP_MEMORY_TAGS
#defineCONFIG_CMDLINE_TAG
總結(jié)
以上是生活随笔為你收集整理的u-boot向linux内核传递启动参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 浙商银行战旗卡分期手续费是多少
- 下一篇: V210 SPI驱动分析