当前位置:   article > 正文

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

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参数:

  1. make -C $DIRPATH RESET_TO_BL31=1 PLAT=xxxx clean
  2. 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开始启动的

  1. func bl31_entrypoint
  2. bl bl31_early_platform_setup
  3. bl bl31_plat_arch_setup
  4. 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的异常向量表.
 

  1. void bl31_main(void)
  2. {
  3. NOTICE("BL31: %s\n", version_string);
  4. NOTICE("BL31: %s\n", build_message);
  5. /* Perform remaining generic architectural setup from EL3 */
  6. bl31_arch_setup();
  7. /* Perform platform setup in BL31 */
  8. bl31_platform_setup();
  9. /* Initialise helper libraries */
  10. bl31_lib_init();
  11. /* Initialize the runtime services e.g. psci */
  12. INFO("BL31: Initializing runtime services\n");
  13. runtime_svc_init();
  14. /*
  15. * All the cold boot actions on the primary cpu are done. We now need to
  16. * decide which is the next image (BL32 or BL33) and how to execute it.
  17. * If the SPD runtime service is present, it would want to pass control
  18. * to BL32 first in S-EL1. In that case, SPD would have registered a
  19. * function to intialize bl32 where it takes responsibility of entering
  20. * S-EL1 and returning control back to bl31_main. Once this is done we
  21. * can prepare entry into BL33 as normal.
  22. */
  23. /*
  24. * If SPD had registerd an init hook, invoke it.
  25. */
  26. if (bl32_init) {
  27. INFO("BL31: Initializing BL32\n");
  28. (*bl32_init)();
  29. }
  30. next_image_type = NON_SECURE;//han han han 也可以是启动non-secure内核
  31. /*
  32. * We are ready to enter the next EL. Prepare entry into the image
  33. * corresponding to the desired security state after the next ERET.
  34. */
  35. bl31_prepare_next_image_entry();
  36. /*
  37. * Perform any platform specific runtime setup prior to cold boot exit
  38. * from BL31
  39. */
  40. bl31_plat_runtime_setup();
  41. }

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)
 

  1. void bl31_prepare_next_image_entry(void)
  2. {
  3. entry_point_info_t *next_image_info;
  4. uint32_t image_type;
  5. /* Determine which image to execute next */
  6. image_type = bl31_get_next_image_type();
  7. /* Program EL3 registers to enable entry into the next EL */
  8. next_image_info = bl31_plat_get_next_image_ep_info(image_type);
  9. assert(next_image_info);
  10. assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr));
  11. INFO("BL31: Preparing for EL3 exit to %s world\n",
  12. (image_type == SECURE) ? "secure" : "normal");
  13. print_entry_point_info(next_image_info);
  14. cm_init_my_context(next_image_info);
  15. cm_prepare_el3_exit(image_type);
  16. }
  1. entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
  2. {
  3. assert(sec_state_is_valid(type));
  4. if (type == NON_SECURE)
  5. return &bl33_image_ep_info;
  6. if (type == SECURE)
  7. return &bl32_image_ep_info;
  8. return NULL;
  9. }
  10. void bl31_early_platform_setup(bl31_params_t *from_bl2,
  11. void *plat_params_from_bl2)
  12. {
  13. ......
  14. bl32_image_ep_info.pc = BL32_BASE;
  15. ......
  16. ......
  17. bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
  18. bl33_image_ep_info.spsr = plat_get_spsr_for_bl33_entry();
  19. ......
  20. }
  21. unsigned long plat_get_ns_image_entrypoint(void)
  22. {
  23. return PLAT_NS_IMAGE_OFFSET;
  24. }

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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/129977
推荐阅读
相关标签
  

闽ICP备14008679号