uboot把内核复制到SDRAM之后,需要跳转到内核的入口函数执行。在跳转之前,还要给内核传递启动参数。传递方式是uboot把启动参数按一定的格式放在指定的地址(位于SDRAM),启动内核之后,内核再去这个地址上读取启动参数。
在uboot源码中搜索do_bootm_linux函数如下:
int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
...
...
boot_prep_linux(images);
boot_jump_linux(images);
return 0;
}
boot_prep_linux函数做的工作就是“把启动参数按一定的格式放在指定的地址”,函数内容如下:
static void boot_prep_linux(bootm_headers_t *images)
{
char *commandline = getenv("bootargs");
...
setup_start_tag(gd->bd);
...
...
setup_commandline_tag(gd->bd, commandline);
setup_memory_tags(gd->bd);
...
setup_initrd_tag(gd->bd, images->rd_start,images->rd_end);
...
setup_end_tag(gd->bd);
}
boot_prep_linux函数把启动参数封装成一个个“tag”,看看setup_start_tag函数的实现,可以得知这些tag被存放在哪个地址上:
可以看到,params结构体的首地址就是存放tag的首地址,在源码中搜索bd->bi_boot_params可以发现,在u-boot-2012.04.01/board/samsung/smdk2440/smdk2440.c文件的board_init函数中有赋值:
也就是uboot在板子初始化的时候就给bd结构体的成员赋了值,bd的全程是board_data,很合理。
setup_commandline_tag是把uboot的“bootargs”参数作为linux的启动参数,查看include/configs/smdk2440.h文件可以知道:
#define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"——bootargs为linux指定了控制台用到的串口和根文件系统存在的区域。
setup_memory_tags告诉linux板子上有几个ram区域,每个区域的大小是多少。
setup_initrd_tag功能不太清楚,先不关心。
设置完启动参数之后,在boot_jump_linux函数中调用kernel_entry(0, machid, r2)函数跳转到linux中。