[41]_uboot启动内核过程和最终宿命

       uboot找到了可支持启动的内核镜像,并不是立马去启动它。为什么不能立马去启动它呢?因为整个内核镜像并不仅仅是内核的有效信息,还有有关内核描述的相关信息,因此先找到内核镜像的启动入口才是关键,下面是详细的过程:

void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
		     bootm_headers_t *images)
{
	ulong	initrd_start, initrd_end;
	ulong	ep = 0;
	bd_t	*bd = gd->bd;
	char	*s;
	int	machid = bd->bi_arch_number;   					// 机器码
	void	(*theKernel)(int zero, int arch, uint params);
	int	ret;

#ifdef CONFIG_CMDLINE_TAG
	char *commandline = getenv ("bootargs");   			//获取命令
#endif

	/* find kernel entry point */			//kernel内核入口不是在起始头部,头部前面可能解压缩代码、镜像格式信息等等。
	if (images->legacy_hdr_valid) {
		ep = image_get_ep (&images->legacy_hdr_os_copy);
#if defined(CONFIG_FIT)
	} else if (images->fit_uname_os) {
		ret = fit_image_get_entry (images->fit_hdr_os, //内核入口于镜像头寻在偏移量
					images->fit_noffset_os, &ep);
		if (ret) {
			puts ("Can't get entry point property!\n");
			goto error;
		}
#endif
	} else {
		puts ("Could not find kernel entry point!\n");
		goto error;
	}
	theKernel = (void (*)(int, int, uint))ep;			//将ep的值赋值给theKernel,这是kernel开始执行的第一句代码

	s = getenv ("machid");
	if (s) {
		machid = simple_strtoul (s, NULL, 16);
		printf ("Using machid 0x%x from environment\n", machid);
	}

	ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM,
			&initrd_start, &initrd_end);
	if (ret)
		goto error;

	show_boot_progress (15);

	debug ("## Transferring control to Linux (at address %08lx) ...\n",
	       (ulong) theKernel);

#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
    defined (CONFIG_CMDLINE_TAG) || \
    defined (CONFIG_INITRD_TAG) || \
    defined (CONFIG_SERIAL_TAG) || \
    defined (CONFIG_REVISION_TAG) || \
    defined (CONFIG_LCD) || \
    defined (CONFIG_VFD) || \
    defined (CONFIG_MTDPARTITION)
	setup_start_tag (bd);		 //这里的bd指的是gd->bd->bi_arch_number ,是前面结果两次转换过来的
#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 (initrd_start && initrd_end)
		setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
	setup_videolfb_tag ((gd_t *) gd);
#endif

#ifdef CONFIG_MTDPARTITION
	setup_mtdpartition_tag();
#endif

	setup_end_tag (bd);
#endif

	/* we assume that the kernel is in place */
	printf ("\nStarting kernel ...\n\n");            //打印出来这一句说明uboot死掉了
							//同时说明uboot成功校验zImage类型、找到kernel的入口地址、成功加载了整个内核到DDR中了
#ifdef CONFIG_USB_DEVICE
	{
		extern void udc_disconnect (void);
		udc_disconnect ();
	}
#endif

	cleanup_before_linux ();

	theKernel (0, machid, bd->bi_boot_params);
	/* does not return */
	return;

error:
	do_reset (cmdtp, flag, argc, argv);    //uboot错误重启
	return;
}
      当然,找到内核入口前还是有很多东西要做的,比如:获取机器码、获取环境变量参数等等,找到内核入口(entry point)然后才开始执行内核第一句代码(theKernel = xxxx)、如果打印出来(Strating Kernel.....),说明了uboot整个阶段(包括第一阶段第二阶段)都是正常的、zImage类型校验成功、找到了kernel所在、机器码、环境变量、kernel入口、并执行了kernel的第一行代码、成功加载内核镜像到DDR并在DDR中执行了内核解压缩的那段代码,至此,uboot负责启动内核的使命就完成了....


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值