bootz启动 Linux内核过程中涉及的 bootz_start 函数

一.  bootz启动Linux

uboot 启动Linux内核使用bootz命令。当然还有其它的启动命令,例如,bootm命令等等。

本文只分析 bootz命令启动 Linux内核的过程中涉及的几个重要函数。

本文继上一篇文章,地址如下:

bootz启动 Linux内核过程中涉及的 do_bootz 函数_凌肖战的博客-CSDN博客

二.  bootz 启动 Linux 内核过程

上一篇文章简单分析,可以知道:

bootz 命令的执行函数为 do_bootz函数。而 do_bootz函数主要调用如下函数:

bootz_start 函数,bootm_disable_interrupts 函数,设置 images.os.os ,do_bootm_states 函数。

1.  bootz_start 函数

bootz_srart 函数也定义在文件 cmd/bootm.c 中,函数内容如下:
static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
			char * const argv[], bootm_headers_t *images)
{
	int ret;
	ulong zi_start, zi_end;

	ret = do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START,
			      images, 1);

	/* Setup Linux kernel zImage entry point */
	if (!argc) {
		images->ep = load_addr;
		debug("*  kernel: default image load address = 0x%08lx\n",
				load_addr);
	} else {
		images->ep = simple_strtoul(argv[0], NULL, 16);
		debug("*  kernel: cmdline image address = 0x%08lx\n",
			images->ep);
	}

	ret = bootz_setup(images->ep, &zi_start, &zi_end);
	if (ret != 0)
		return 1;

	lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);

	/*
	 * Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
	 * have a header that provide this informaiton.
	 */
	if (bootm_find_images(flag, argc, argv))
		return 1;

#ifdef CONFIG_SECURE_BOOT
	extern uint32_t authenticate_image(
			uint32_t ddr_start, uint32_t image_size);
	if (authenticate_image(images->ep, zi_end - zi_start) == 0) {
		printf("Authenticate zImage Fail, Please check\n");
		return 1;
	}
#endif
	return 0;
}

7 行,调用函数 do_bootm_states ,执行 BOOTM_STATE_START 阶段。
12 行,设置 images ep 成员变量,也就是系统镜像的入口点。
使用 bootz 命令启动 系统时,就会设置系统在 DRAM 中的存储位置,这个存储位置就是系统镜像的入口点,因 此, images->ep=0X80800000
21 行,调用 bootz_setup 函数,此函数会判断当前的系统镜像文件是否为 Linux 的镜 像文件,并且会打印出镜像相关信息, bootz_setup 函数稍后会讲解。
第 31 行,调用函数 bootm_find_images 查找 ramdisk 和设备树 (dtb) 文件,但是我们没有 用到 ramdisk ,因此,此函数在这里仅仅用于查找设备树 (dtb) 文件。

来看一下 bootz_setup 函数,此函数定义在文件 arch/arm/lib/bootm.c 中,函数内容如下:
#define	LINUX_ARM_ZIMAGE_MAGIC	0x016f2818

int bootz_setup(ulong image, ulong *start, ulong *end)
{
	struct zimage_header *zi;

	zi = (struct zimage_header *)map_sysmem(image, 0);
	if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
		puts("Bad Linux ARM zImage magic!\n");
		return 1;
	}

	*start = zi->zi_start;
	*end = zi->zi_end;

	printf("Kernel image @ %#08lx [ %#08lx - %#08lx ]\n", image, *start,
	      *end);

	return 0;
}

1 行,宏 LINUX_ARM_ZIMAGE_MAGIC 就是 ARM Linux 系统魔术数。
zimage_header 的zi_magic为 zImage 的幻数,魔术数。应该为0x016f2818。前面有9个32位的数据,那么9*4=36,0~35,第36个字节的数据开始就是zimage的幻数。可以通过查看 编译好的 zImage文件,确认第36个字节数据是否为 这个魔术值。
7 行,从传递进来的参数 image( 也就是系统镜像首地址 ) 中获取 zimage 头。 zImage 结构体为 zimage_header
8~11 行,判断 image 是否为 ARM Linux 系统镜像,如果不是的话就直接返回,并且打印出 “ Bad Linux ARM zImage magic! ”。
13-14 行初始化函数 bootz_setup 的参数 start end
16 行,打印启动信息,如果 Linux 系统镜像正常的话。

你可能感兴趣的:(uboot,系统移植篇,linux,arm开发)