u-boot启动内核过程(5)

来源:互联网 发布:淘宝联盟找优惠券 编辑:程序博客网 时间:2024/06/05 11:03
u-boot启动内核过程分析:

u-boot启动内核s = getenv ("bootdelay");  //读取环境变量run_command (s, 0);   //执行命令bootdelay: nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0nand read.jffs2 0x30007FC0 kernel:

说明:
1.从nand的kernel分区读出内核到内存0x30007FC0 中去:
2.这里的kernel是个分区名字,它在代码中被写死,我们关心它的偏移值和大小,使用mtd命令:



3.这里也可以写成nand read.jffs2 0x30007FC0  0x0060000 0x00200000
输入?nand ======》 nand nand read[.jffs2]     - addr off|partition size)
4.nand read.jffs2读的时候不用考虑页对齐
5.如何修改分区: 它的宏在100ask24x0.h (include\configs)
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \
                            "128k(params)," \
                            "2m(kernel)," \
                            "-(root)"

bootm 0x30007FC0:
1.根据头部移动内核到合适的地方。



u-boot定义了一个image_header结构体,其中两个成员:uint32_tih_load;/* Data Load  Address  加载地址*/uint32_tih_ep;/* Entry Point Address 入口地址*/如果这个加载地址=内核实际的地址就会直接执行if(ntohl(hdr->ih_load) == data)......else   memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); /*将地址移动到加载地址*/


说明:0x30007FC0这个地址为什么这么奇怪?
我们的uImage是由一个头部和真正的内核构成,其中头部为64字节,而规定加载地址为0x30008000
所以将入口地址定义为0x30007FC0,这样就不需要移动内核,提高了启动时间

2.启动内核
do_bootm_linux  (cmdtp, flag, argc, argv ,addr, len_ptr, verify);
2.1 设置启动参数
   利用了tag结构体:


struct tag_header {
u32 size;
u32 tag;
};  /*表示标记的类型和长度*/
不同的类型它们的union结构体内容不一样:
内存时:tag_mem32
命令行:tag_cmdline
设置tag,传递给内核:



params = (struct tag *) bd->bi_boot_params;  // 参数在内存中的地址params->hdr.tag = ATAG_CORE;   //表示起始tagparams->hdr.size = tag_size (tag_core);  //该tag的大小,以字节为单位    params = tag_next (params);    //指向当前标记的末尾#define tag_next(t)((struct tag *)((u32 *)(t) + (t)->hdr.size))  


params->hdr.tag = ATAG_MEM;   //表示内存tagparams->u.mem.start = bd->bi_dram[i].start;  //内存起始地址params->u.mem.size = bd->bi_dram[i].size;  //内存大小


bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0 /*命令行字符串*/params->hdr.tag = ATAG_CMDLINE;   //表示命令行tagparams->hdr.size =(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;  //大小strcpy (params->u.cmdline.cmdline, p);   //命令行


    2.2 跳到入口地址启动内核void (*theKernel)(int zero, int arch, uint params);  /*定义一个函数指针*/theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); /* 初始化这个函数指针,指向入口地址,即内核处*/theKernel (0, bd->bi_arch_number, bd->bi_boot_params);  /*运行这个函数指针*/






0 0