Chinaunix首页 | 论坛 | 博客
  • 博客访问: 400531
  • 博文数量: 101
  • 博客积分: 2247
  • 博客等级: 大尉
  • 技术积分: 979
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-15 22:39
文章分类

全部博文(101)

文章存档

2012年(1)

2011年(100)

分类: 嵌入式

2011-06-29 14:53:40

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内核代码执行。

阅读(1299) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~