本文转载自:https://blog.csdn.net/hovan/article/details/42520879

trust zone之我见知道,支持trustzone的芯片会跑在两个世界。

普通世界、安全世界,对应高通这边是HLOS,QSEE。

如下图:

如下是HLOS与QSEE的软件架构图

HLOS这两分为kernel层,user层。user层的通过qseecom提供的API起动trustzone那边的app。

qseecom driver 除了提供API,还调用scm函数做世界切换。

scm driver 那边接到qseecom的调用后,会把HLOS相关数据(包括指令参数)放入指它buffer,然后执行scm调用。

qsapp通过qsee提供的api接受来自HLOS那边的请求,并把执行结果返回HLOS。

qsee除了提供API,还与从monitor把来自HLOS的数据传给qsapp,然后把qsapp的数据返回给HLOS。

monitor就不用说了,切换世界用的,还处理shared buffer的内容。

是大概的架构图,细节比较复杂,没有开元。

下面通过一个简单的qseecom_security_test代码来说明整个调用流程。

如下图:

qseecom_security_test.c

 
  1. int main( int argc, char *argv[] )

  2. {

  3. ....

  4. /* Initialize the global/statics to zero */

  5. memset( g_qseeCommHandles, 0, sizeof(g_qseeCommHandles) );

  6. memset( g_xors, 0, sizeof(g_xors) );

先初始化全局变量g_qseeCommHandles

 
  1. for( j = 0; j < NUM_CLIENTS; j++ ) {

  2. /* Initialize the barriers to ensure that commands aren't sent before the listeners

  3. * have been started. Otherwise, errors will be generated.

  4. */

  5. ret = sem_init( &barrier[j], 0, 0 );//初始化一个信号量

  6. if( ret ) {

  7. LOGD( "barrier init failed %i, %i", ret, errno );

  8. g_err = -1;

  9. break;

  10. }

  11. ret = pthread_create( &threads[j], NULL, &test_thread, (void*)j );//创建test_thread线程

  12. }

初始化一个barrier信号变量,用于线程创建时的同步

然后调用pthread_create()函数创建test_thread线程,该线程将会起动QSApp。

 
  1. void *test_thread( void* threadid )

  2. {

  3. ...

  4. do {

  5. .....

  6. LOGD( "T%#X: Starting QSApp...", (uint32_t)threadid );

  7. ret = QSEECom_start_app( &g_qseeCommHandles[tid][0], "/firmware/image",//起动名为securitytest的QSApp

  8. "securitytest", sizeof(qseecom_req_res_t)*2 );

  9. LOGD( "T%#X: Started QSApp...", (uint32_t)threadid );

  10. CHECK_RETURN( ret, __LINE__ );

跟着来到test_thread线程

调用QSEECom_start_app()函数起动QSApp。

这个函数在kernel实现 如下:

qseecom.c

 
  1. static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)

  2. {

  3. ...

  4. /* Get the handle of the shared fd */

  5. ihandle = ion_import_dma_buf(qseecom.ion_clnt,

  6. load_img_req.ifd_data_fd);

  7. ...

  8. /* SCM_CALL to load the app and get the app_id back */

  9. ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,

  10. sizeof(struct qseecom_load_app_ireq),

  11. &resp, sizeof(resp));

Get shared buf fd,用于与安全世界通信

调用scm_call()来陷入安全世界。

scm_call()实现如下:

arch/arm/mach-msm/scm.c

 
  1. int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,

  2. void *resp_buf, size_t resp_len)

  3. {

  4. ...

  5. ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf,

  6. resp_len, cmd, len);

  7. kfree(cmd);

  8. return ret;

  9. }

scm_call_common的实现如下:

 
  1. static int scm_call_common(u32 svc_id, u32 cmd_id, const void *cmd_buf,

  2. size_t cmd_len, void *resp_buf, size_t resp_len,

  3. struct scm_command *scm_buf,

  4. size_t scm_buf_length)

  5. {

  6. ....

  7. mutex_lock(&scm_lock);

  8. ret = __scm_call(scm_buf);//调用

  9. mutex_unlock(&scm_lock);

  10. if (ret)

  11. return ret;

  12. rsp = scm_command_to_response(scm_buf);

  13. start = (unsigned long)rsp;

  14. do {

  15. scm_inv_range(start, start + sizeof(*rsp));

  16. } while (!rsp->is_complete);

  17. end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;

  18. scm_inv_range(start, end);

  19. if (resp_buf)

  20. memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);

  21. return ret;

  22. }

调用__scm_call()陷入安全世界,回来后调用scm_get_response_buffer()获取安全世界返回的信息供上面QSApp client用

__scm_call实现如下:

 
  1. static int __scm_call(const struct scm_command *cmd)

  2. {

  3. ...

  4. ret = smc(cmd_addr);

  5. ...

  6. return ret;

  7. }

smc实现如下:

 
  1. static u32 smc(u32 cmd_addr)

  2. {

  3. int context_id;

  4. register u32 r0 asm("r0") = 1;

  5. register u32 r1 asm("r1") = (u32)&context_id;

  6. register u32 r2 asm("r2") = cmd_addr;

  7. do {

  8. asm volatile(

  9. __asmeq("%0", "r0")

  10. __asmeq("%1", "r0")

  11. __asmeq("%2", "r1")

  12. __asmeq("%3", "r2")

  13. #ifdef REQUIRES_SEC

  14. ".arch_extension sec\n"

  15. #endif

  16. "smc #0 @ switch to secure world\n"

  17. : "=r" (r0)

  18. : "r" (r0), "r" (r1), "r" (r2)

  19. : "r3");

  20. } while (r0 == SCM_INTERRUPTED);

  21. return r0;

  22. }

是一段汇编程序,好吧,安全世界的QSApp已经运行起来了,当QSApp完成相应服务后就会返回数据。这个函数就会返回。

Starting QSApp已经完成,下面就注册listener,这个listener用于监听QSApp那边的请求。因为有时QSApp也需要HLOS这边做一些事。

实现如下:

 
  1. void *listener_thread( void* threadid )

  2. {

  3. ....

  4. do {

  5. ...

  6. /* Register as a listener with the QSApp */

  7. LOGD( "L%#X: Registering as listener with QSApp...", (uint32_t)threadid );

  8. ret = QSEECom_register_listener( &g_qseeCommHandles[parent_tid][tid], GET_LSTNR_SVC_ID(parent_tid, tid),

  9. sizeof(qseecom_req_res_t), 0 );

  10. ....

  11. for( ;; ) {

  12. /* Wait for request from the QSApp */

  13. ret = QSEECom_receive_req( g_qseeCommHandles[parent_tid][tid], req_res, sizeof(qseecom_req_res_t) );

  14. if( ret ) break;

  15. ....

  16. /* Send the response to the QSApp */

  17. ret = QSEECom_send_resp( g_qseeCommHandles[parent_tid][tid], req_res, sizeof(qseecom_req_res_t) );

  18. CHECK_RETURN( ret, __LINE__ );

  19. }

  20. } while( 0 );

  21. ...

  22. }

这个函数比较长,简化一下,分步来看

首先调用QSEECom_register_listener()函数来注册监听,告诉QSApp,我可以接收你的申请。

再次看到for循环没有,这就是一直等待QSApp那边的消息,一但有消息QSEECom_reveive_req就返回,这边处理完之后。

再调用qSEECom_send_resp()发送response给QSApp。

无论是起动QSApp,还是注册listener都是线程中执行,一但所有线程都退出后就会调用QSEECom_shutdown_app()函数停止QSApp。

整个过程执行完毕。如下:

 
  1. void *test_thread( void* threadid )

  2. {

  3. ...

  4. if ( g_qseeCommHandles[tid][0] != NULL ) {

  5. QSEECom_shutdown_app( &g_qseeCommHandles[tid][0] );

  6. }

  7. } while( 0 );

  8. pthread_exit( NULL );

  9. return NULL;

  10. }

注:QSEECom _XX开头的函数都在kernel中的qseecom.c里实现,scm系统调用,都在scm.c中实现。

HLOS user层把握QSEEComAPI.h文件

HLOS kernel层把握qseecom.c 和 scm.c两文件

谢谢

--------------------- 本文来自 hovan-邓永坚 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/hovan/article/details/42674055?utm_source=copy

高通msm8916平台QSEE之trustzone分析

从硬件背景上看TZ是在ARMv6的架构上产生的,在ARMv7上重新设计了,TZ的目的是提供一个软硬件都安全的环境,安全的环境是单独的运行在一个硬件空间,和非安全的进行了硬件上的隔离。

QSEE主要负责加载APP,以及安全APP的堆栈管理,提供安全的API接口,安全的字符操作和LOG功能

QSAPPS是高通开发的APP,运行在QSEE之上

用户空间通过加载并调用QSEEAPP来是实现一些安全数据或敏感操作的加密

QSEEComAPIlib是暴露给HLOS的API,HLOS客户端和监听端利用QSEEComdriver通过这些API来和QSEE进行数据的收和发。

QSEEComclient是需要调用QSEECom_start_app来得到一个句柄指向QSEECom字符设备,并且可以用这个句柄来进行数据的首发

QSEEComlistener需要用QSEECom_register_listener来注册,可以注册多个listener,每个listener所在的线程将会被挂起,直到接收到包含到该listener的信息。

QSEEComdriver是一个字符型设备,通过IOCTL来和QSEECom进行通讯,这些IOCTL都应该被QSEEComAPI进行调用

因为qsee不开源 tz部分只能看到少量符号

所以主要从用户和开发角度观察tz

开发需要开发相应的qsapp来实现安全的一些数据操作

用户态中需要加载相应的qsapp,并且利用qsapplib提供的API来和qsapp进行通讯

而qsapp如何与qsee进行通讯的呢

qsapp则调用scm来将数据保存到安全空间

为什么tz能实现安全呢

从硬件上 就区分了两个世界,安全世界用一根总线,非安全世界用一根总线

非安全世界的操作无法访问到安全世界

必须通过qsee中的scm调用来访问

而用户操作只能访问qsapp

所以达到了安全保护的作用

高通msm8916平台QSEE之trustzone分析

转自http://www.it610.com/article/5292101.htm

简谈高通Trustzone的实现【转】的更多相关文章

  1. 简谈高通Trustzone的实现

    从trust zone之我见知道,支持trustzone的芯片会跑在两个世界. 普通世界.安全世界,对应高通这边是HLOS,QSEE. 如下图: 如下是HLOS与QSEE的软件架构图 HLOS这两分为 ...

  2. 高通Trustzone and QSEE介绍

    http://blog.csdn.net/iamliuyanlei/article/details/52625968

  3. 浅谈Android高通(Qualcomm)和联发科(MTK)平台

    一款CPU好不好是要从多个方面考虑的,并不是说简简单单看一个主频.几个核心数就完了,更重要的是它的综合实力到底有多强,这里面当然也会牵扯到价格问题,性能相似当然是便宜的获胜,这是毋庸置疑的. 事实上, ...

  4. .NET简谈接口

    自从面向对象开发方式的出现,抽象的概念就开始日新月异的发展,面向对象编程.面向接口编程.面向组件编程等等:这一系列的概念都是软件工程所追求的思想范畴,高类聚低耦合. 今天我要简谈的是面向对象里面非常重 ...

  5. 高通、猎户机型Android典型bootloader分析

    1.bootloader是什么? 简单地说,bootloader 就是在操作系统内核运行之前运行的一段小程序.通过这段小程序,我们可以初始化硬件设备.建立内存空间的映射图,从而将系统的软硬件环境带到一 ...

  6. 高通 MSM8K bootloader : SBL1 .

    一. MSM8K Boot Flow 图1: 高通MSM8K平台bootloader启动流程基本类似,但具体各平台,比如MSM8974.MSM8916.MSM8994等,会有微小区别. 从上图,可以看 ...

  7. 高通android开发摘要

    一部分是开源的,可以从codeaurora.org上下载,还有一部分是高通产权的,需要从高通的网站上下载. 将高通产权的代码放到:vendor/qcom/proprietary 1. 设置bms一些参 ...

  8. 高通 MSM8K bootloader之一: SBL1

    MSM8K Boot Flow  转自:http://www.cnblogs.com/liang123/p/6325257.html            http://blog.csdn.net/F ...

  9. linux驱动由浅入深系列:PBL-SBL1-(bootloader)LK-Android启动过程详解之一(高通MSM8953启动实例)

    转自:http://blog.csdn.net/radianceblau/article/details/73229005 http://www.aiuxian.com/article/p-14142 ...

随机推荐

  1. 删除server服务文件

    某用户升级ArcGIS for Server后,出现了之前版本server中的服务残留的现象,且服务访问不正常,怎样彻底删除的残留文件. 即怎样删除ArcGIS for Server中发布的某个服务涉 ...

  2. js_常见特效——点击切换_背景颜色_收起与展开

    <script src="../js/jquery-1.8.3.min.js"></script><script type="text/ja ...

  3. QQ公众号?是的,你没看错!

    微信公众平台培育了800多万的微信公众号,自身也通过微信游戏.广告分销等找到了一些增值盈利模式.作为同门大师兄,qq也在11月份推出了QQ公众号,第一个手机QQ上的“生活服务号”——YTO圆通速递上线 ...

  4. windows安装并破解navicat.

    1:下载以下两个文件. patchNavicat.exe:  https://pan.baidu.com/s/1ZtV20GUGfZHcXHRTEb5tYg navicatforMysql.exe:  ...

  5. gradle build scan

    1:gradle build scan 用于视图审查 构建步骤如下  https://guides.gradle.org/creating-build-scans/?_ga=2.80362963.59 ...

  6. PAT Battle Over Cities [未作]

    1013 Battle Over Cities (25)(25 分) It is vitally important to have all the cities connected by highw ...

  7. Maven项目常见错误解决方法汇总

    issue 1.Java compiler level does not match the version of the installed Java project facet. 或者 One o ...

  8. ID和Name

    ID和Name都可以用来标识一个标记,Javascript分别有两个方法getElementById和getElementByName来定位Dom节点. 区别如下: 1.我们知道在网页做Post提交时 ...

  9. Java-二分查找算法

    package com.lym.binarySearch; import java.util.Arrays; /** * 二分查找 * * @author Administrator * */ pub ...

  10. Selenium Webdriver——操作隐藏的元素(四)

    页面上弹出的对话框是自动化测试经常会遇到的一个问题:很多情况下对话框是一个iframe,如上一节中介绍的例子,处理起来稍微有点麻烦:但现在很多前端框架的对话框是div 形式的,这就让我们的处理变得十分 ...