[IMX6Q]u-boot启动kernel流程

u-boot版本:v2009.08


u-boot利用了env里的cmd来实现调用boot linux的接口, 效果等同于在u-boot中敲"booti xxx..."

start_armboot -> board_late_init:

int board_late_init(void)
{
	int ret = 0;
#ifdef MX6Q_SABRESD_ANDROID_H
	switch (get_boot_device()) {
	case SD_BOOT:
		if (!getenv("fastboot_dev"))
			setenv("fastboot_dev", "mmc2");
		/*本例的boot device是SD,并且device number是2*/
		if (!getenv("bootcmd"))
			setenv("bootcmd", "booti mmc2");
		break;
......
	}
#endif
......
	return 0;
}
start_armboot ->main_loop:

void main_loop (void)
{
......
	/*获取前面set的bootcmd,值是"booti mmc2"*/
	s = getenv ("bootcmd");

	debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
	/*如果u-boot开机阶段没有收到按键事件,那么就去启动kernel*/
	if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
......
# ifndef CONFIG_SYS_HUSH_PARSER
		/*调用booti mmc2去boot linux*/
		run_command (s, 0);
# else
......
}
booti命令对应的定义如下:

U_BOOT_CMD(
	booti,	3,	1,	do_booti,
	"booti   - boot android bootimg from memory\n",
	"[<addr> | mmc0 | mmc1 | mmc2 | mmcX] [<partition>] \n    - boot application image stored in memory or mmc\n"
	"\t'addr' should be the address of boot image which is zImage+ramdisk.img\n"
	"\t'mmcX' is the mmc device you store your boot.img, which will read the boot.img from 1M offset('/boot' partition)\n"
	"\t 'partition' (optional) is the partition id of your device, if no partition give, will going to 'boot' partition\n"
);
do_booti:

int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
......
	if (mmcc != -1) {
#ifdef CONFIG_MMC
......
		/*获取device信息*/
		mmc = find_mmc_device(mmcc);
		if (!mmc) {
			printf("booti: cannot find '%d' mmc device\n", mmcc);
			goto fail;
		}
......
#ifdef CONFIG_ANDROID_BOOT_PARTITION_MMC
#ifdef CONFIG_ANDROID_RECOVERY_PARTITION_MMC
		/*开机可能是进入正常boot模式,也可以是进入recovery模式,取决于传进来的参数,本例是kernel*/
		if (!strcmp(ptn, "boot"))
			partno = CONFIG_ANDROID_BOOT_PARTITION_MMC;
		if (!strcmp(ptn, "recovery"))
			partno = CONFIG_ANDROID_RECOVERY_PARTITION_MMC;
		/*获取kernel对应的partition info*/
		if (get_partition_info(dev_desc, partno, &info)) {
			printf("booti: device don't have such partition:%s\n", ptn);
			goto fail;
		}
#endif
#endif

#ifdef CONFIG_FASTBOOT
......
#else
		/*获取kernel的hdr,此信息是在编译boot.img的时候就存放在它起始的某个固定位置。*/
		if (mmc->block_dev.block_read(mmcc, info.start,
					      1, (void *)hdr) < 0) {
			printf("booti: mmc failed to read bootimg header\n");
			goto fail;
		}
......
		sector = info.start + (hdr->page_size / 512);
#endif
		/*读取kernel到RAM中的kernel_addr*/
		if (mmc->block_dev.block_read(mmcc, sector,
					      (hdr->kernel_size / 512) + 1,
					      (void *)hdr->kernel_addr) < 0) {
			printf("booti: mmc failed to read kernel\n");
			goto fail;
		}
		/* flush cache after read */
		flush_cache((ulong)hdr->kernel_addr, hdr->kernel_size); /* FIXME */
		sector += ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) / 512;
		/*读取ramdisk到kernel的ramdisk_addr*/
		if (mmc->block_dev.block_read(mmcc, sector,
					      (hdr->ramdisk_size / 512) + 1,
					      (void *)hdr->ramdisk_addr) < 0) {
			printf("booti: mmc failed to read kernel\n");
			goto fail;
		}
		/* flush cache after read */
		flush_cache((ulong)hdr->ramdisk_addr, hdr->ramdisk_size); /* FIXME */
#else
		return -1;
#endif
	} else {
		......
	}
......
	/*根据hdr信息来boot linux*/
	do_booti_linux(hdr);
......
}

void do_booti_linux (boot_img_hdr *hdr)
{
	ulong initrd_start, initrd_end;
#ifdef CONFIG_SERIAL_TAG
	char appended_cmd_line[512];
#endif
	void (*theKernel)(int zero, int arch, uint params);
	bd_t *bd = gd->bd;
#ifdef CONFIG_CMDLINE_TAG
	char *commandline = getenv("bootargs");

	/* If no bootargs env, just use hdr command line */
	/*本例bootargs没有定义*/
	if (!commandline) {
		/*获取cmdline,此值在device/fsl/imx6/BoardConfigCommon.mk中定义。*/
		commandline = (char *)hdr->cmdline;
......
    }
#endif
	/*kernel address就是boot kernel的函数指针地址了*/
	theKernel = (void (*)(int, int, uint))(hdr->kernel_addr);
	/*获取ramdisk start 和 end地址*/
	initrd_start = hdr->ramdisk_addr;
	initrd_end = initrd_start + hdr->ramdisk_size;

	/*将memory,serial,revision,commandline等都放在各自
	的struct tag中,kernel启动之后会解析它们。*/
#if defined (CONFIG_SETUP_MEMORY_TAGS)
	setup_start_tag(bd);
#ifdef CONFIG_SERIAL_TAG
	setup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAG
	setup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
	setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
	setup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAG
	if (hdr->ramdisk_size)
		setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
......
	setup_end_tag (bd);
#endif
......
	/*启动kernel, never return back!*/
	theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
}
注意theKernel()的参数,第二个是machine type,kernel会去匹配,如果没有找到对应的type id,那么就无法正常启动kernel.

int board_init(void)
{
......
	/* board id for linux */
	gd->bd->bi_arch_number = MACH_TYPE_MX6Q_SABRESD;
......
}
第三个参数就是前面的那些tags.

到此,kernel就启动起来了。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值