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[] ){....  /* Initialize the global/statics to zero */  memset( g_qseeCommHandles, 0, sizeof(g_qseeCommHandles) );  memset( g_xors, 0, sizeof(g_xors) );

先初始化全局变量g_qseeCommHandles

  1. for( j = 0; j < NUM_CLIENTS; j++ ) {      /* Initialize the barriers to ensure that commands aren't sent before the listeners       * have been started.  Otherwise, errors will be generated.       */      ret = sem_init( &barrier[j], 0, 0 );//初始化一个信号量      if( ret ) {        LOGD( "barrier init failed %i, %i", ret, errno );        g_err = -1;        break;      }      ret = pthread_create( &threads[j], NULL, &test_thread, (void*)j );//创建test_thread线程    }

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

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

  1. void *test_thread( void* threadid ){  ...  do {.....    LOGD( "T%#X: Starting QSApp...", (uint32_t)threadid );    ret = QSEECom_start_app( &g_qseeCommHandles[tid][0], "/firmware/image",//起动名为securitytest的QSApp            "securitytest", sizeof(qseecom_req_res_t)*2 );    LOGD( "T%#X: Started QSApp...", (uint32_t)threadid );    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){.../* Get the handle of the shared fd */        ihandle = ion_import_dma_buf(qseecom.ion_clnt,                  load_img_req.ifd_data_fd);.../*  SCM_CALL  to load the app and get the app_id back */       ret = scm_call(SCM_SVC_TZSCHEDULER, 1,  &load_req,          sizeof(struct qseecom_load_app_ireq),           &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,       void *resp_buf, size_t resp_len){   ... ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf,               resp_len, cmd, len);    kfree(cmd); return ret;}

scm_call_common的实现如下:

  1. static int scm_call_common(u32 svc_id, u32 cmd_id, const void *cmd_buf,             size_t cmd_len, void *resp_buf, size_t resp_len,                struct scm_command *scm_buf,                size_t scm_buf_length){ ....    mutex_lock(&scm_lock);  ret = __scm_call(scm_buf);//调用  mutex_unlock(&scm_lock);    if (ret)        return ret; rsp = scm_command_to_response(scm_buf); start = (unsigned long)rsp; do {        scm_inv_range(start, start + sizeof(*rsp)); } while (!rsp->is_complete); end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;   scm_inv_range(start, end);  if (resp_buf)       memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);   return ret;}

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

__scm_call实现如下:

  1. static int __scm_call(const struct scm_command *cmd){...    ret = smc(cmd_addr);... return ret;}

smc实现如下:

  1. static u32 smc(u32 cmd_addr){   int context_id; register u32 r0 asm("r0") = 1;  register u32 r1 asm("r1") = (u32)&context_id;   register u32 r2 asm("r2") = cmd_addr;   do {        asm volatile(           __asmeq("%0", "r0")         __asmeq("%1", "r0")         __asmeq("%2", "r1")         __asmeq("%3", "r2")#ifdef REQUIRES_SEC          ".arch_extension sec\n"#endif           "smc    #0  @ switch to secure world\n"         : "=r" (r0)         : "r" (r0), "r" (r1), "r" (r2)          : "r3");    } while (r0 == SCM_INTERRUPTED);    return r0;}

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

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

实现如下:

  1. void *listener_thread( void* threadid ){....  do {...    /* Register as a listener with the QSApp */    LOGD( "L%#X: Registering as listener with QSApp...", (uint32_t)threadid );    ret = QSEECom_register_listener( &g_qseeCommHandles[parent_tid][tid], GET_LSTNR_SVC_ID(parent_tid, tid),            sizeof(qseecom_req_res_t), 0 );....    for( ;; ) {      /* Wait for request from the QSApp */      ret = QSEECom_receive_req( g_qseeCommHandles[parent_tid][tid], req_res, sizeof(qseecom_req_res_t) );      if( ret ) break;     ....      /* Send the response to the QSApp */      ret = QSEECom_send_resp( g_qseeCommHandles[parent_tid][tid], req_res, sizeof(qseecom_req_res_t) );      CHECK_RETURN( ret, __LINE__ );    }  } while( 0 );...}

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

首先调用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 ){...if ( g_qseeCommHandles[tid][0] != NULL ) {      QSEECom_shutdown_app( &g_qseeCommHandles[tid][0] );    }  } while( 0 );  pthread_exit( NULL );  return NULL;}

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

HLOS user层把握QSEEComAPI.h文件

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

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

  1. 简谈高通Trustzone的实现【转】

    本文转载自:https://blog.csdn.net/hovan/article/details/42520879 从trust zone之我见知道,支持trustzone的芯片会跑在两个世界. 普 ...

  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. window环境搭建zookeeper,kafka集群

    为了演示集群的效果,这里准备一台虚拟机(window 7),在虚拟机中搭建了单IP多节点的zookeeper集群(多IP节点的也是同理的),并且在本机(win 7)和虚拟机中都安装了kafka. 前期 ...

  2. Python3 MySQL 数据库连接

    什么是 PyMySQL? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb. PyMySQL 遵循 Python 数据库 AP ...

  3. Spring Security 基础登录实例

    1 新建Java Web项目 导入Jar: 2 修改web.xml <?xml version="1.0" encoding="UTF-8"?> & ...

  4. Android开发学习之路--基于vitamio的视频播放器(一)

      之前也试过vitamio这个库,后来不知道被什么事情给耽搁了,就没继续下去.近来觉得视频还是需要学习一下的,谁让直播那么火呢,就想着写一个简单的视频播放的app先吧.好了那就开始吧,暂时取名为JP ...

  5. Android Multimedia框架总结(十七)音频开发基础知识

    请尊重分享成果,转载请注明出处,本文来自逆流的鱼yuiop,原文链接:http://blog.csdn.net/hejjunlin/article/details/53078828 近年来,唱吧,全民 ...

  6. 没有文件扩展“.js”的脚本引擎问题解决

    安装MinGW的时候提示没有文件扩展".js"的脚本引擎. 原因:系统安装Dreamwear.UltraEdit.EditPlus后修改了.js文件的默认打开方式.当想直接执行js ...

  7. Spark技术内幕: Shuffle详解(三)

    前两篇文章写了Shuffle Read的一些实现细节.但是要想彻底理清楚这里边的实现逻辑,还是需要更多篇幅的:本篇开始,将按照Job的执行顺序,来讲解Shuffle.即,结果数据(ShuffleMap ...

  8. MTK8127源码编译出现的错误及相关解决办法

    /** * date:2016/8/17 * author: Y.X .YANG */ 按照开发文档提示: 1.MTK提供的开发包目录下有若干个.aa .ab .ac ...的分压缩包.此时应当将这些 ...

  9. 基于V4L2摄像头采集图片程序设计

    #ifndef __COMMON_H #define __COMMON_H //该头文件定义的是摄像头在屏幕上显示的宽度和高度 #include<stdio.h> #include< ...

  10. 关于MySQL-python-1.2.3.tar.gz安装失败的解决方案

    关于MySQL-python-1.2.3.tar.gz安装失败的解决方案 RHEL6.4升级到python2.7.9,然后安装 MySQL-python-1.2.3.tar.gz, 报错.解决错误之后 ...