7.OP-TEE+qemu的启动过程分析--加载optee_os和rootfs

    历经一年多时间的系统整理合补充,《手机安全和可信应用开发指南:TrustZone与OP-TEE技术详解 》一书得以出版,书中详细介绍了TEE以及系统安全中的所有内容,全书按照从硬件到软件,从用户空间到内核空间的顺序对TEE技术详细阐述,读者可从用户空间到TEE内核一步一步了解系统安全的所有内容,同时书中也提供了相关的示例代码,读者可根据自身实际需求开发TA。目前该书已在天猫、京东、当当同步上线,链接如下(麻烦书友购书时能给予评论,多谢多谢)

京东购买地址

当当购买地址

天猫购买地址

非常感谢在此期间大家的支持以及各位友人的支持和帮助!!!。

为方便和及时的回复读者对书中或者TEE相关的问题的疑惑,也为了大家能有一个统一的交流平台。我搭建了一个简单的论坛,网址如下:

https://www.huangtengxq.com/discuz/forum.php

关于您的疑问可在“相关技术讨论“”中发帖,我会逐一回复。也欢迎大家发帖,一起讨论TEE相关的一些有意思的feature。共同交流。同时该论坛中也会添加关于移动端虚拟化的相关技术的板块,欢迎各位共同交流学习

 

  

启动过程中entry.S文件通过汇报调用main_init_sec函数将optee-os image. kernel image和rootfs加载到RAM中,并定位device tree地址信息,以备kernel和OP-TEE启动使用,这些操作是由main_init_sec函数,该函数定义在bios_qemu_tz_arm/bios/main.c文件中,本文将介绍main_init_sec函数的执行流程和具体操作。

main_init_sec的完整的流程图如下:

7.OP-TEE+qemu的启动过程分析--加载optee_os和rootfs_第1张图片

main_init_sec函数内容和代码注释如下

 

void main_init_sec(struct sec_entry_arg *arg)
{
	void *fdt;
	int r;
	const uint8_t *sblob_start = &__linker_secure_blob_start;	//定义OP-TEE OS image的存放的起始地址
	const uint8_t *sblob_end = &__linker_secure_blob_end; //定义OP-TEE OS image的存放的末端地址
	struct optee_header hdr;    //存放OP-TEE OS image头的信息
	size_t pg_part_size;    //OP-TEE OS image除去初始化头部的信息的大小
	uint32_t pg_part_dst;    //OP-TEE OS image除去初始化头部信息后在RAM中的起始地址

	msg_init();    //初始化uart

	/* Find DTB */
/* 加载device tree 信息,在qemu工程中,并未将device tree信息编译到Bios.bin中,而默认存放在DTB_START地址中 */
	fdt = open_fdt(DTB_START, &__linker_nsec_dtb_start,
			&__linker_nsec_dtb_end);
	r = fdt_pack(fdt);
	CHECK(r < 0);

	/* Look for a header first */
/* 判定OP-TEE OS image的大小是否大于image header的大小 */
	CHECK(((intptr_t)sblob_end - (intptr_t)sblob_start) <
		(ssize_t)sizeof(hdr));

/* 将OP-TEE OS image header信息拷贝到hdr变量中 */
	copy_bios_image("secure header", (uint32_t)&hdr, sblob_start,
			sblob_start + sizeof(hdr));

/* 校验OP-TEE OS image header中的magic和版本信息是否合法 */
	CHECK(hdr.magic != OPTEE_MAGIC || hdr.version != OPTEE_VERSION);

	msg("found secure header\n");
	sblob_start += sizeof(hdr);	//将sblob_start的值后移到除去image header的位置
	CHECK(hdr.init_load_addr_hi != 0);	//检查OP-TEE OS的初始化加载地址是否为零

/* 获取OP-TEE OS除去 image header和ini操作部分代码的大小 */
	pg_part_size = sblob_end - sblob_start - hdr.init_size;

/* 确定存放OP-TEE OS除去image header和init操作部分代码后存放在RAM中的地址 */
	pg_part_dst = (size_t)TZ_RES_MEM_START + TZ_RES_MEM_SIZE - pg_part_size;

/* 将存放OP-TEE OS除去image header和init操作部分后的内容拷贝到RAM中 */
	copy_bios_image("secure paged part",
			pg_part_dst, sblob_start + hdr.init_size, sblob_end);

	sblob_end -= pg_part_size;	//重新计算sblo_end的地址,剔除page part

	arg->paged_part = pg_part_dst;	//将pg_part_dst赋值给arg中的paged_part以备跳转执行OP-TEE OS使用
	arg->entry = hdr.init_load_addr_lo;    //将hdr.init_load_addr_lo赋值给arg中的entry,该地址为op-TEE OS的入口地址

	/* Copy secure image in place */
/* 将OP-TEE OS的实际image拷贝到其实地址为hdr.init_load_addr_l的RAM地址中 */
	copy_bios_image("secure blob", hdr.init_load_addr_lo, sblob_start,
			sblob_end);

	/*
	 * Copy NS images as while we can read the secure flash from where
	 * we load them.
	 */
/* 拷贝kernel image, rootfs到RAM,并拷贝device tree到对应地址,以备被kernel使用 */
	copy_ns_images();、

/* 将device tree的地址赋值给arg->fdt变量,以备OP-TEE OS启动使用 */
	arg->fdt = dtb_addr;

	msg("Initializing secure world\n");
}

Note:在qemu.mk工程中,OP-TEE image中是没有paged part部分的,这点从启动log就而已看出

 

7.OP-TEE+qemu的启动过程分析--加载optee_os和rootfs_第2张图片
  该函数执行完成之后,将会返回结构体为sec_entry_arg的变量,该变量在接下来启动OP-TEE OS的时候很重要,该变量将会告诉CPU OP-TEE OS的入口地址,device tree的地址以及paged_part的地址。

  main_init_sec函数执行完成之后会返回到entry.S中继续执行,接下来所执行的汇编代码如下:

 

pop {r0, r1, r2}
mov ip, r0  /* entry address */
mov r0, r1  /* argument (address of pagable part if != 0) */ 
blx ip 

  在执行完main_init_sec函数自后, OP-TEE OS的entry地址将会被存放在r0寄存器中,而paged part部分的起始地址将会被存放咋r1寄存器中。使用pop指令执行出栈操作,然后使用mov指令,将存放了OP-TEE OS image的entry address的值赋值给ip寄存器,将paged part的起始地址赋值给r0寄存器,最后调用blx ip指令,进入OP-TEE OS的启动操作。等OP-TEE OS启动完成之后,则会再次跳转会entry.s文件中继续执行,接下来会通过调用main_init_ns函数去启动Linux kernel。

 

 

你可能感兴趣的:(OP-TEE,ARM,TrustZone技术)