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

京东购买地址

当当购买地址

天猫购买地址

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

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

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

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

  

如果个系统有ATF(ARM Trusted Frimware)(ARF的部分,请参考ATF的相关文档),OP-TEE OS属于bl32阶段被启动,通过在bl31阶段调用opteed_enter_sp函数跳转到OP-TEE OS中执行启动操作。而在使用qemu+OP-TEE的环境中,运行时,如果启动OP-TEE OS请参考《7.OP-TEE+qemu的启动过程分析--加载optee_os和rootfs》。

  以qemu+OP-TEE的方式运行TEE时,OP-TEE的image的链接文件是:optee_os/core/arch/arm/kernel/kern.ld.S,在该文件中中可以得知TEE image启动的时的入口函数是_start函数,代码如下:

  _start函数被定义在core/arch/arm目录中的不同文件中,根据不同的板级拥有不同的.S文件。在qemu中使用的时候,使用的是ARM32,故本例子中使用QEMU+OPTEE运行TEE时,使用的是ARM32,所以入口函数被定义在core/arch/arm/kernel/generic_entry_a32.S文件中。整个启动的大致流程图如下(只考虑主CPU的启动):

  该文件的主要内容如下,整个流程从_start函数开始,然后跳转到reset操作,最重要的是执行reset_primary函数:

.section .data
.balign 4#ifdef CFG_BOOT_SYNC_CPU
.equ SEM_CPU_READY, 1
#endif#ifdef CFG_PL310
.section .rodata.init
panic_boot_file:.asciz __FILE__/** void assert_flat_mapped_range(uint32_t vaddr, uint32_t line)*/
.section .text.init
/* __assert_flat_mapped_range 函数,判定MMU中虚拟地址和物理地址的映射关系是否正常  */
LOCAL_FUNC __assert_flat_mapped_range , :
UNWIND( .fnstart)
UNWIND( .cantunwind)push    { r4-r6, lr }mov    r4, r0mov   r5, r1bl    cpu_mmu_enabledcmp  r0, #0beq   1fmov   r0, r4bl    virt_to_physcmp r0, r4beq   1f/** this must be compliant with the panic generic routine:* __do_panic(__FILE__, __LINE__, __func__, str)*/ldr    r0, =panic_boot_filemov    r1, r5mov   r2, #0mov   r3, #0bl    __do_panicb .       /* should NOT return */
1:  pop { r4-r6, pc }
UNWIND( .fnend)
END_FUNC __assert_flat_mapped_range/* panic if mmu is enable and vaddr != paddr (scratch lr) */
/* assert_flat_mapped_range宏,如果MMU使能但虚拟地址和物理地址不匹配则引起panic */.macro assert_flat_mapped_range va, lineldr  r0, =(\va)ldr  r1, =\linebl   __assert_flat_mapped_range.endm
#endif /* CFG_PL310 */.weak plat_cpu_reset_early
/* CPU重置 */
FUNC plat_cpu_reset_early , :
UNWIND( .fnstart)bx lr
UNWIND( .fnend)
END_FUNC plat_cpu_reset_early
KEEP_PAGER plat_cpu_reset_early.section .text.boot
/* _start函数,跳转到reset执行 */
FUNC _start , :b    resetb  .   /* Undef */b    .   /* Syscall */b  .   /* Prefetch abort */b   .   /* Data abort */b   .   /* Reserved */b .   /* IRQ */b  .   /* FIQ */
END_FUNC _start/* 准备非主CPU进入ready */.macro cpu_is_ready
#ifdef CFG_BOOT_SYNC_CPUbl  get_core_poslsl r0, r0, #2ldr   r1,=sem_cpu_syncldr    r2, =SEM_CPU_READYstr  r2, [r1, r0]dsbsev
#endif.endm/* 等待主CPU */.macro wait_primary
#ifdef CFG_BOOT_SYNC_CPUldr r0, =sem_cpu_syncmov   r2, #SEM_CPU_READYsev
1:ldr   r1, [r0]cmp r1, r2wfenebne  1b
#endif.endm/* 等待从CPU */.macro wait_secondary
#ifdef CFG_BOOT_SYNC_CPUldr r0, =sem_cpu_syncmov   r3, #CFG_TEE_CORE_NB_COREmov    r2, #SEM_CPU_READYsev
1:subs  r3, r3, #1beq   3fadd   r0, r0, #4
2:ldr   r1, [r0]cmp r1, r2wfenebne  2bb 1b
3:
#endif.endm/** Save boot arguments* entry r0, saved r4: pagestore* entry r1, saved r7: (ARMv7 standard bootarg #1)* entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2)* entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0)*/
/* 保存启动的时候传入的参数:page table, dta, linux kernel entry address, bootarg */.macro bootargs_entry
#if defined(CFG_NS_ENTRY_ADDR)ldr   r5, =CFG_NS_ENTRY_ADDR
#elsemov    r5, lr
#endif
#if defined(CFG_PAGEABLE_ADDR)ldr   r4, =CFG_PAGEABLE_ADDR
#elsemov    r4, r0
#endif
#if defined(CFG_DT_ADDR)ldr r6, =CFG_DT_ADDR
#elsemov    r6, r2
#endifmov   r7, r1.endm/* reset函数定义,执行主要启动操作 */
LOCAL_FUNC reset , :
UNWIND( .fnstart)
UNWIND( .cantunwind)bootargs_entry  //保存传入的启动参数/* Enable alignment checks and disable data and instruction cache. */
/* 使能对齐检查并禁用cache */read_sctlr r0orr    r0, r0, #SCTLR_Abic r0, r0, #SCTLR_Cbic r0, r0, #SCTLR_Iwrite_sctlr r0isb/* Early ARM secure MP specific configuration */
/* 重置CPU的特殊配置 */bl  plat_cpu_reset_earlyldr r0, =_startwrite_vbar r0#if defined(CFG_WITH_ARM_TRUSTED_FW)b  reset_primary   //当支持ATF的时候只执行reset_primary完成OP-TEE的启动
#elsebl get_core_pos    //获取当前cpu的ID,用来判定当前执行的cortex是否是主CPUcmp   r0, #0beq   reset_primary   //如果当前CPU是主CPU,则执行reset_primary来完成OP-TEE的启动b reset_secondary //执行其他CPU的初始化操作,主CPU不会执行到这里
#endif
UNWIND( .fnend)
END_FUNC reset/** Setup sp to point to the top of the tmp stack for the current CPU:* sp is assigned stack_tmp + (cpu_id + 1) * stack_tmp_stride -* stack_tmp_offset*/
/* 设置SP的值为栈顶 */.macro set_spbl  get_core_poscmp r0, #CFG_TEE_CORE_NB_CORE/* Unsupported CPU, park it before it breaks something */bge   unhandled_cpuadd    r0, r0, #1ldr   r2, =stack_tmp_strideldr   r1, [r2]mul r2, r0, r1ldr   r1, =stack_tmpadd  r1, r1, r2ldr   r2, =stack_tmp_offsetldr   r2, [r2]sub sp, r1, r2.endm/** Cache maintenance during entry: handle outer cache.* End address is exclusive: first byte not to be changed.* Note however arm_clX_inv/cleanbyva operate on full cache lines.** Use ANSI #define to trap source file line number for PL310 assertion*/.macro __inval_cache_vrange vbase, vend, line
#ifdef CFG_PL310assert_flat_mapped_range (\vbase), (\line)bl    pl310_baseldr   r1, =(\vbase)ldr   r2, =(\vend)bl arm_cl2_invbypa
#endifldr   r0, =(\vbase)ldr   r1, =(\vend)bl arm_cl1_d_invbyva.endm.macro __flush_cache_vrange vbase, vend, line
#ifdef CFG_PL310assert_flat_mapped_range (\vbase), (\line)ldr   r0, =(\vbase)ldr   r1, =(\vend)bl arm_cl1_d_cleanbyvabl   pl310_baseldr   r1, =(\vbase)ldr   r2, =(\vend)bl arm_cl2_cleaninvbypa
#endifldr   r0, =(\vbase)ldr   r1, =(\vend)bl arm_cl1_d_cleaninvbyva.endm#define inval_cache_vrange(vbase, vend) \__inval_cache_vrange (vbase), ((vend) - 1), __LINE__#define flush_cache_vrange(vbase, vend) \__flush_cache_vrange (vbase), ((vend) - 1), __LINE__#ifdef CFG_BOOT_SYNC_CPU
#define flush_cpu_semaphores \flush_cache_vrange(sem_cpu_sync, \(sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2)))
#else
#define flush_cpu_semaphores
#endif/* reset_primary函数,执行主CPU的主要初始化操作 */
LOCAL_FUNC reset_primary , :
UNWIND( .fnstart)
UNWIND( .cantunwind)/* preserve r4-r7: bootargs */#ifdef CFG_WITH_PAGER/** Move init code into correct location and move hashes to a* temporary safe location until the heap is initialized.** The binary is built as:* [Pager code, rodata and data] : In correct location* [Init code and rodata] : Should be copied to __text_init_start* [Hashes] : Should be saved before initializing pager**/
/* 拷贝init section 到RAM中 */ldr   r0, =__text_init_start /* dst */ldr    r1, =__data_end    /* src */ldr    r2, =__tmp_hashes_end  /* dst limit *//* Copy backwards (as memmove) in case we're overlapping */sub  r2, r2, r0      /* len */add    r0, r0, r2add   r1, r1, r2ldr   r2, =__text_init_start
copy_init:ldmdb r1!, {r3, r8-r12, sp}stmdb  r0!, {r3, r8-r12, sp}cmp    r0, r2bgt   copy_init
#endif#ifdef CFG_CORE_SANITIZE_KADDRESS/* First initialize the entire shadow area with no access */ldr  r0, =__asan_shadow_start   /* start */ldr  r1, =__asan_shadow_end /* limit */mov  r2, #ASAN_DATA_RED_ZONE
shadow_no_access:str    r2, [r0], #4cmp r0, r1bls   shadow_no_access/* Mark the entire stack area as OK */ldr   r2, =CFG_ASAN_SHADOW_OFFSETldr r0, =__nozi_stack_start    /* start */lsr  r0, r0, #ASAN_BLOCK_SHIFTadd    r0, r0, r2ldr   r1, =__nozi_stack_end  /* limit */lsr  r1, r1, #ASAN_BLOCK_SHIFTadd    r1, r1, r2mov   r2, #0
shadow_stack_access_ok:strb r2, [r0], #1cmp r0, r1bls   shadow_stack_access_ok
#endifset_sp/* complete ARM secure MP common configuration */bl plat_cpu_reset_late     //完成ARM安全内存保护的基本配置/* Enable Console */bl    console_init    //初始化串口#ifdef CFG_PL310bl   pl310_basebl    arm_cl2_config
#endif/** Invalidate dcache for all memory used during initialization to* avoid nasty surprices when the cache is turned on. We must not* invalidate memory not used by OP-TEE since we may invalidate* entries used by for instance ARM Trusted Firmware.*/
/* 无效cache操作 */
#ifdef CFG_WITH_PAGERinval_cache_vrange(__text_start, __tmp_hashes_end)
#elseinval_cache_vrange(__text_start, __end)
#endif#ifdef CFG_PL310/* Enable PL310 if not yet enabled */bl   pl310_basebl    arm_cl2_enable
#endifbl    core_init_mmu_map   //初始化MMU的内存映射表bl    core_init_mmu_regs  //初始化MMU中的寄存器映射bl   cpu_mmu_enable  //使能MMUbl   cpu_mmu_enable_icache   //使能指令cachebl   cpu_mmu_enable_dcache   //使能data cachemov   r0, r4      /* pageable part address */mov  r1, r5      /* ns-entry address */mov   r2, r6      /* DT address */
/* 执行主要初始化操作,带入page part 地址,linux kernel入口地址, DT地址 */bl    generic_boot_init_primary   mov r4, r0      /* save entry test vector *//** In case we've touched memory that secondary CPUs will use before* they have turned on their D-cache, clean and invalidate the* D-cache before exiting to normal world.*/
/* 清空cache */
#ifdef CFG_WITH_PAGERflush_cache_vrange(__text_start, __init_end)
#elseflush_cache_vrange(__text_start, __end)
#endif/* release secondary boot cores and sync with them */
/* 同步从核的启动 */cpu_is_readyflush_cpu_semaphoreswait_secondary#ifdef CFG_PL310_LOCKED/* lock/invalidate all lines: pl310 behaves as if disable */bl    pl310_basebl    arm_cl2_lockallwaysbl   pl310_basebl    arm_cl2_cleaninvbyway
#endif/** Clear current thread id now to allow the thread to be reused on* next entry. Matches the thread_init_boot_thread() in* generic_boot.c.*/bl    thread_clr_boot_thread  //清空当前线程的ID值,以备被重新使用#if defined(CFG_WITH_ARM_TRUSTED_FW)/* Pass the vector address returned from main_init */mov r1, r4
#else/* realy standard bootarg #1 and #2 to non secure entry */mov  r4, #0mov   r3, r6      /* std bootarg #2 for register R2 */mov r2, r7      /* std bootarg #1 for register R1 */mov r1, #0
#endif /* CFG_WITH_ARM_TRUSTED_FW *//* 触发smc调用,如果支持ATF,则返回TEESMC_OPTEED_RETURN_ENTRY_DONE的值到EL3中,通知ATF OPTEE已经启动完成。如果不支持ATF,则同样触发smc调用,切换到no-secure world状态进行linux kernel的启动 */mov   r0, #TEESMC_OPTEED_RETURN_ENTRY_DONEsmc #0b .   /* SMC should not return */
UNWIND( .fnend)
END_FUNC reset_primaryLOCAL_FUNC unhandled_cpu , :
UNWIND( .fnstart)wfib   unhandled_cpu
UNWIND( .fnend)
END_FUNC unhandled_cpu#if defined(CFG_WITH_ARM_TRUSTED_FW)
FUNC cpu_on_handler , :
UNWIND( .fnstart)
UNWIND( .cantunwind)mov r4, r0mov   r5, r1mov   r6, lrread_sctlr r0orr  r0, r0, #SCTLR_Awrite_sctlr r0ldr   r0, =_startwrite_vbar r0mov    r4, lrset_spbl  core_init_mmu_regsbl    cpu_mmu_enablebl    cpu_mmu_enable_icachebl cpu_mmu_enable_dcachemov    r0, r4mov   r1, r5bl    generic_boot_cpu_on_handlerbx   r6
UNWIND( .fnend)
END_FUNC cpu_on_handler#else /* defined(CFG_WITH_ARM_TRUSTED_FW) *//* 从核的启动函数 */
LOCAL_FUNC reset_secondary , :
UNWIND( .fnstart)
UNWIND( .cantunwind)wait_primaryset_spbl    plat_cpu_reset_late#if defined (CFG_BOOT_SECONDARY_REQUEST)/* if L1 is not invalidated before, do it here */bl  arm_cl1_d_invbysetway
#endifbl    core_init_mmu_regsbl    cpu_mmu_enablebl    cpu_mmu_enable_icachebl cpu_mmu_enable_dcachecpu_is_ready#if defined (CFG_BOOT_SECONDARY_REQUEST)/* generic_boot_core_hpen return value (r0) is ns entry point */bl generic_boot_core_hpen
#elsemov    r0, r5      /* ns-entry address */
#endifbl    generic_boot_init_secondarymov  r0, #TEESMC_OPTEED_RETURN_ENTRY_DONEmov r1, #0mov   r2, #0mov   r3, #0mov   r4, #0smc   #0b .   /* SMC should not return */
UNWIND( .fnend)
END_FUNC reset_secondary
#endif /* defined(CFG_WITH_ARM_TRUSTED_FW) */

10.OP-TEE OS启动(一)相关推荐

  1. Android手机启动流程与TEE OS

    2019独角兽企业重金招聘Python工程师标准>>> 转载:https://cloud.tencent.com/developer/article/1043659 一个移植了TEE ...

  2. 【CA-TA实战系列六】CA与TA背后的故事一:TEE OS

    一.前言 TEE OS就是可信环境的操作系统,这里我们的参考资料是前辈的<手机安全和可信应用开发指南>,因此这里我们的TEE OS就是OP TEE. 那么为什么在搞TA CA的设计实现要关 ...

  3. TEE OS中断篇(五):FIQ的事件处理

    到上一篇的时候,CPU已经具备了执行下一步handler的上下文,推出了EL3,进军了EL1,这里来看看在tee os里面到底干了啥? 1 OP-TEE对FIQ事件的处理 OP-TEE启动时会调用th ...

  4. 《深入理解Spark:核心思想与源码分析》——3.10节创建和启动ExecutorAllocationManager...

    本节书摘来自华章社区<深入理解Spark:核心思想与源码分析>一书中的第3章,第3.10节创建和启动ExecutorAllocationManager,作者耿嘉安,更多章节内容可以访问云栖 ...

  5. uboot启动流程概述_Alibaba Cloud Linux 2 LTS OS 启动优化实践

    Alibaba Cloud Linux 2 (原Aliyun Linux 2)是阿里云操作系统团队基于社区版 4.19 LTS 内核打造的一款针对云产品优化的下一代 Linux 操作系统发行版,不仅提 ...

  6. 在linux oracle 10g/11g x64bit环境中,goldengate随os启动而自己主动启动的脚本

    在linux oracle 10g/11g x64bit环境中,goldengate随os启动而自己主动启动的脚本 在linux.oracle 10g/11g x64bit环境中,goldengate ...

  7. 10.2.0.5启动enterprise manager

    10.2.0.5启动enterprise manager OEM作为一个实用工具,随着10g和11g的普及,OEM功能越来越强大,oem也应用越来越广泛.但是如果是10.2.0.5的版本,并且安装时间 ...

  8. 修改weblogic(10.3)域的启动JDK

    修改weblogic(10.3)域的启动JDK 说明: 1.D:\bea为笔者weblogic安装目录 2.D:\bea\user_projects\domains\base_domain为笔者域创建 ...

  9. Windows 10和Linux脚本启动jar包服务器,并设置开机启动

    Windows 10和Linux脚本启动jar包服务器,并设置开机启动 现在好多Java服务和应用都是用jar启动,jar打包成的里面会直接带有tomcat,所以可以直接启动,但是如何通过脚本启动并且 ...

最新文章

  1. 再见了SpringMVC,这个框架有点厉害,甚至干掉了Servlet!
  2. 安装Mysql提示1045错误解决方法
  3. 软考广东有哪几个考点
  4. JavaScript面向对象——封装及相关原理解析
  5. matlab207a,MATLAB教程R2012a课后习题答案
  6. 使用 ExecuteMultiple 提高批量数据加载的性能
  7. linux指令ls -1,linux命令1--ls
  8. 云单元架构,如何赋能数字化转型呢?
  9. 想将有色彩的视频进行去色处理就这样做
  10. 优质文章推荐(第一期)
  11. php 公众号推送图片尺寸,微信公众号推送文图片什么尺寸最佳?
  12. Select at least one project的解决方法
  13. Pytorch报错解决:The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimensio
  14. jQuery-放大镜
  15. 【转】韩寒:跳出棋盘的棋子
  16. NodeBB – 基于 Node.js 的开源论坛系统
  17. 花式登录正方教务系统
  18. 数学乐 --- 科学计数法(个人学习笔记)
  19. Nacos微服务注册发现、配置和管理微服务
  20. 单片机c语言p1口转弯灯实验,单片机p1口转弯灯实验程序

热门文章

  1. ipad wifi信号测试软件,真香!平板Ipad无线投屏在电视上视频教程分享,无需装软件,支持任何显示设备...
  2. Vert.x -- web的介绍(三)
  3. mysql数据库 二次开发_Dedesql数据库类详解(二次开发必备教程)
  4. (一)老毛桃U盘启动盘制作
  5. 可以帮我做一个python的3D飞机小游戏吗
  6. 【融职培训】Web前端学习 第3章 JavaScript基础教程18 BOM概述
  7. MFC关于进程使用:创建、关闭及查询进程
  8. adobe air 工程师_基于HTML的Adobe AIR应用程序的新窗口
  9. String你真的会吗?不会还不进来!!!是等我胖虎锤各位呢?!!!
  10. 汇编语言 | 基础知识