1.U-Boot使用标记列表(tagged list)的方式向Linux传递参数。
标记的数据结构式是tag,在U-Boot源代码目录中定义:
u-boot-2011.06-rc3/arch/arm/include/asm/setup.h
struct tag_header {
u32 size;
u32 tag;
};
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_videotext videotext;
struct tag_ramdisk ramdisk;
struct tag_initrd initrd;
struct tag_serialnr serialnr;
struct tag_revision revision;
struct tag_videolfb videolfb;
struct tag_cmdline cmdline;
/*
* Acorn specific
*/
struct tag_acorn acorn;
/*
* DC21285 specific
*/
struct tag_memclk memclk;
} u;
};
2.U-Boot使用命令bootm来启动已经加载到内存中的内核。而bootm命令实际上调用的是do_bootm函数。对于Linux内核,do_bootm函数会调用do_bootm_linux函数来设置标记列表和启动内核。
do_bootm_linux函数在u-boot-2011.06-rc3/arch/avr32/lib/bootm.c 中定义如下:
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
{
void (*theKernel)(int magic, void *tagtable);
struct tag *params, *params_start;
char *commandline = getenv("bootargs");
if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
return 1;
theKernel = (void *)images->ep;
show_boot_progress (15);
params = params_start = (struct tag *)gd->bd->bi_boot_params;
params = setup_start_tag(params);
params = setup_memory_tags(params);
if (images->rd_start) {
params = setup_ramdisk_tag(params,
PHYSADDR(images->rd_start),
PHYSADDR(images->rd_end));
}
params = setup_commandline_tag(params, commandline);
params = setup_clock_tags(params);
params = setup_ethernet_tags(params);
params = setup_boardinfo_tag(params);
setup_end_tag(params);
printf("\nStarting kernel at %p (params at %p)...\n\n",
theKernel, params_start);
prepare_to_boot();
theKernel(ATAG_MAGIC, params_start);
/* does not return */
return 1;
}
注意其中的setup_start_tag,setup_memory_tags,setup_end_tag函数。
3.U-Boot设置好标记列表后就要调用内核了。但调用内核前,CPU必须满足下面的条件:
(1)CPU寄存器的设置
r0=0
r1=机器码
r2=内核参数标记列表在RAM中的起始地址
(2)CPU工作模式
禁止IRQ与FIQ中断
CPU为SVC模式
(3)使数据Cache与指令Cache失效
4.在do_bootm_linux函数中将内核的入口地址“images->ep”强制类型转换为函数指针。根据ATPCS规则,函数的参数个数不超过4个时,使用r0~r3这4个寄存器来传递参数。因此第128行的函数调用则会将0放入r0,机器码machid放入r1,内核参数地址bd->bi_boot_params放入r2,从而完成了寄存器的设置,最后转到内核的入口地址。
到这里,U-Boot的工作就结束了,系统跳转到Linux内核代码执行。
阅读(1330) | 评论(0) | 转发(0) |