ATF(ARM Trusted firmware)完成启动流程

ARM TrustZone技术简介 -- 3 (BL31 Secure Monitor简介)

在使用TrustZone技术的嵌入式设备当中,无法避免的需要解决从非安全侧切换到安全侧的问题,而为了完成这个切换,需要一个专用的进行非安全上下文和安全上下文切换的固件,这个固件一般我们称为arm trust firmware,在ARM官方维护的github中我们能够下载到其完整的代码

https://github.com/ARM-software/arm-trusted-firmware

在其github工程的介绍里,有完整的arm trusted firmware的移植和适配的方法,所以可以很方便的将其移植到不同的平台并进行适配,自己的操作系统。

arm trusted firmware的工作方法如下图所示

图中的EL3 Firmware就是BL31,也就是arm trusted firmware,通过其框图我们可以看到其包括多个组成部分,第一级是一个中断处理入口叫做 SMC interface,其用汇编代码写成,用来接收来自非安全侧或者是安全侧的SMC指令造成的陷入到EL3的异常请求,然后SMC Interface根据其SMC 指令中传入的立即数,通过Service Router进行处理函数分发,按照分类主要的处理分发分为非安全世界和安全世界的World Switcher,一些需要在EL3访问的硬件资源的驱动类代码,最后是一大类的PSCI电源管理模块(包括挂起处理器,恢复处理器运行,处理器的上下电等PSCI电源管理的内容)。

其中我们着重分析World Switch和PSCI的部分,个人对特殊的EL3硬件访问接口所知不多,所以不做介绍。

1, World Switch

非安全世界和安全世界的切换,这个是arm trusted firmware的主要功能,其中的主要功能集中在service/spd 目录中然后其根据不同的安全OS的操作系统来进行不同的Dispatch,所以这里的spd是 Secure Payload Dispatch的简写,其根据SMC FID的不同来选择不同的optee_smc_handler, trusty_smc_handler, tspd_smc_handler来对具体的命令来进行处理。

比如 TSP_PREEMPT是当运行在安全侧的时候非安全侧的IRQ中断发生了,从而触发了中断当前安全侧业务,切换到非安全侧执行中断处理函数,然后再返回安全侧的动作。

而 TSP_EL1_INTERRUPT是和TSP_PREEMPT相反的动作。

而在optee_smc_handler这些具体的SMC中断处理函数中有对其具体命令的具体处理。

2, PSCI电源管理

如果不知道PSCI是什么那么请参考

http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf

在标准的Linux操作系统的处理器电源管理通用接口中,对ARM处理器有专用的PSCI模块,来对CPU的上线和离线进行处理,其中包括了对中断的迁移,对处理器状态切换的保存,而在最终的操作硬件的阶段,可以通过对设备树的PSCI模块进行配置从而选择使用什么SMC指令或者HYP指令将当前的处理器进行挂起恢复,上电和下电。

ARM TrustZone技术简介更像是一个简单的介绍和怎样把整个系统串起来的线索,如果对其中的具体实现很感兴趣,可以具体阅读代码,也许后面我会写一些代码分析的博客,来更详细的介绍其中的细节。 (代码分析是写书最快的途径....但是实际上对读者对系统架构的了解作用了了)
 

----------------------------------------------------------------

[ATF]-ATF启动--BL31跳转到optee和uboot

 

1、背景

在vendor某些厂商的设计中,ATF并不是BOOTROM加载后的第一个启动镜像,可能是这样的:
BOOTROM—>PL—>ATF—>optee—>uboot…, 在PL阶段就已经将ATF/optee/uboot镜像的load到内存了.

2、ATF编译

由上述背景的原因,我们的ATF就不需要走BL1/BL2阶段load optee/uboot镜像到内存了,直接走BL3即可.
所以bl1和bl2目录也无需编译.

我们的编译方法是在make的时候传入RESET_TO_BL31=1参数:

make -C $DIRPATH RESET_TO_BL31=1 PLAT=xxxx clean
make -C $DIRPATH RESET_TO_BL31=1 PLAT=xxx xxxx_VDK=0 xxxxxx=0 xxxxxx=0 HIGHADDR_DEVICE=1 all

3、ATF的启动

从bl31.ld.S文件可知,ATF是从bl31_entrypoint开始启动的

func bl31_entrypoint
	bl	bl31_early_platform_setup
	bl	bl31_plat_arch_setup
	bl	bl31_main

在bl31_main()函数中:

runtime_svc_init()跳转optee之前的准备,然后再调用bl32_init跳转到optee,optee
os初始化完成后再从此处回来。
bl31_prepare_next_image_entry()跳转uboot之前的准备,返回到bl31_entrypoint后调用b
el3_exit跳转到uboot, PC就不会再回此处了。下次PC再回来就是在REE进行了smc调用,那时是直接跳转到ATF的异常向量表.
 

void bl31_main(void)
{
	NOTICE("BL31: %s\n", version_string);
	NOTICE("BL31: %s\n", build_message);

	/* Perform remaining generic architectural setup from EL3 */
	bl31_arch_setup();

	/* Perform platform setup in BL31 */
	bl31_platform_setup();

	/* Initialise helper libraries */
	bl31_lib_init();

	/* Initialize the runtime services e.g. psci */
	INFO("BL31: Initializing runtime services\n");
	runtime_svc_init();

	/*
	 * All the cold boot actions on the primary cpu are done. We now need to
	 * decide which is the next image (BL32 or BL33) and how to execute it.
	 * If the SPD runtime service is present, it would want to pass control
	 * to BL32 first in S-EL1. In that case, SPD would have registered a
	 * function to intialize bl32 where it takes responsibility of entering
	 * S-EL1 and returning control back to bl31_main. Once this is done we
	 * can prepare entry into BL33 as normal.
	 */

	/*
	 * If SPD had registerd an init hook, invoke it.
	 */
	if (bl32_init) {
		INFO("BL31: Initializing BL32\n");
		(*bl32_init)();
	}


     next_image_type = NON_SECURE;//han han han 也可以是启动non-secure内核
	/*
	 * We are ready to enter the next EL. Prepare entry into the image
	 * corresponding to the desired security state after the next ERET.
	 */
	bl31_prepare_next_image_entry();

	/*
	 * Perform any platform specific runtime setup prior to cold boot exit
	 * from BL31
	 */
	bl31_plat_runtime_setup();
}

4、获取optee/uboot的跳转地址

bl31_prepare_next_image_entry()可以获取optee/uboot的跳转地址,该地址最终来自于platform_def.h头文件中写死的地址

#define BL32_BASE (PLAT_S_DRAM_BASE + BL31_SIZE + PLAT_TRUSTED_MAILBOX_SIZE)
#define PLAT_NS_IMAGE_BASE 0x80000000
#define PLAT_NS_IMAGE_OFFSET (PLAT_NS_IMAGE_BASE + 0x9000000)
 

void bl31_prepare_next_image_entry(void)
{
	entry_point_info_t *next_image_info;
	uint32_t image_type;

	/* Determine which image to execute next */
	image_type = bl31_get_next_image_type();

	/* Program EL3 registers to enable entry into the next EL */
	next_image_info = bl31_plat_get_next_image_ep_info(image_type);
	assert(next_image_info);
	assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));

	INFO("BL31: Preparing for EL3 exit to %s world\n",
		(image_type == SECURE) ? "secure" : "normal");
	print_entry_point_info(next_image_info);
	cm_init_my_context(next_image_info);
	cm_prepare_el3_exit(image_type);
}
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
	assert(sec_state_is_valid(type));
	if (type == NON_SECURE)
		return &bl33_image_ep_info;

	if (type == SECURE)
		return &bl32_image_ep_info;

	return NULL;
}

void bl31_early_platform_setup(bl31_params_t *from_bl2,
				void *plat_params_from_bl2)
{
	......
	bl32_image_ep_info.pc = BL32_BASE;
	......
	......
	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
	bl33_image_ep_info.spsr = plat_get_spsr_for_bl33_entry();
	......
}

unsigned long plat_get_ns_image_entrypoint(void)
{
	return PLAT_NS_IMAGE_OFFSET;
}

4、总结一下ATF启动流程

在这里插入图片描述

 

-------------------------------------------------------------------------------------------------------------------------------

ATF将系统启动从最底层进行了完整的统一划分,将secure monitor的功能放到了bl31中进行,这样当系统完全启动之后,在CA或者TEE OS中触发了smc或者是其他的中断之后,首先是遍历注册到bl31中的对应的service来判定具体的handle,这样可以对系统所有的关键smc或者是中断操作做统一的管理和分配。ATF的code boot整个启动过程框图如下:

  在上述启动过程中,每个Image跳转到写一个image的方式各不相同,下面将列出启动过程中每个image跳转到下一个image的过程:

1. bl1跳转到bl2执行

  在bl1完成了bl2 image加载到RAM中的操作,中断向量表设定以及其他CPU相关设定之后,在bl1_main函数中解析出bl2 image的描述信息,获取入口地址,并设定下一个阶段的cpu上下文,完成之后,调用el3_exit函数实现bl1到bl2的跳转操作,进入到bl2中执行.

2.bl2跳转到bl31执行

  在bl2中将会加载bl31, bl32, bl33的image到对应权限的RAM中,并将该三个image的描述信息组成一个链表保存起来,以备bl31启动bl32和bl33使用.在AACH64中,bl31位EL3 runtime software,运行时的主要功能是管理smc指令的处理和中断的主力,运行在secure monitor状态中

  bl32一般为TEE OS image,本章节以OP-TEE为例进行说明

  bl33为非安全image,例如uboot, linux kernel等,当前该部分为bootloader部分的image,再由bootloader来启动linux kernel.

  从bl2跳转到bl31是通过带入bl31的entry point info调用smc指令触发在bl1中设定的smc异常来通过cpu将全向交给bl31并跳转到bl31中执行。

3.bl31跳转到bl32执行

  在bl31中会执行runtime_service_inti操作,该函数会调用注册到EL3中所有service的init函数,其中有一个service就是为TEE服务,该service的init函数会将TEE OS的初始化函数赋值给bl32_init变量,当所有的service执行完init后,在bl31中会调用bl32_init执行的函数来跳转到TEE OS的执行

4.bl31跳转到bl33执行

  当TEE_OS image启动完成之后会触发一个ID为TEESMC_OPTEED_RETURN_ENTRY_DONE的smc调用来告知EL3 TEE OS image已经完成了初始化,然后将CPU的状态恢复到bl31_init的位置继续执行。

  bl31通过遍历在bl2中记录的image链表来找到需要执行的bl33的image。然后通过获取到bl33 image的镜像信息,设定下一个阶段的CPU上下文,退出el3然后进入到bl33 image的执行。

https://blog.csdn.net/shuaifengyun/article/details/72468109

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值