简谈高通Trustzone的实现【转】
本文转载自: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
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
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。
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
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
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的实现如下:
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实现如下:
static int __scm_call(const struct scm_command *cmd){...ret = smc(cmd_addr);...return ret;}
smc实现如下:
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这边做一些事。
实现如下:
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。
整个过程执行完毕。如下:
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两文件
谢谢
--------------------- 本文来自 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
所以达到了安全保护的作用
简谈高通Trustzone的实现【转】的更多相关文章
- 简谈高通Trustzone的实现
从trust zone之我见知道,支持trustzone的芯片会跑在两个世界. 普通世界.安全世界,对应高通这边是HLOS,QSEE. 如下图: 如下是HLOS与QSEE的软件架构图 HLOS这两分为 ...
- 高通Trustzone and QSEE介绍
http://blog.csdn.net/iamliuyanlei/article/details/52625968
- 浅谈Android高通(Qualcomm)和联发科(MTK)平台
一款CPU好不好是要从多个方面考虑的,并不是说简简单单看一个主频.几个核心数就完了,更重要的是它的综合实力到底有多强,这里面当然也会牵扯到价格问题,性能相似当然是便宜的获胜,这是毋庸置疑的. 事实上, ...
- .NET简谈接口
自从面向对象开发方式的出现,抽象的概念就开始日新月异的发展,面向对象编程.面向接口编程.面向组件编程等等:这一系列的概念都是软件工程所追求的思想范畴,高类聚低耦合. 今天我要简谈的是面向对象里面非常重 ...
- 高通、猎户机型Android典型bootloader分析
1.bootloader是什么? 简单地说,bootloader 就是在操作系统内核运行之前运行的一段小程序.通过这段小程序,我们可以初始化硬件设备.建立内存空间的映射图,从而将系统的软硬件环境带到一 ...
- 高通 MSM8K bootloader : SBL1 .
一. MSM8K Boot Flow 图1: 高通MSM8K平台bootloader启动流程基本类似,但具体各平台,比如MSM8974.MSM8916.MSM8994等,会有微小区别. 从上图,可以看 ...
- 高通android开发摘要
一部分是开源的,可以从codeaurora.org上下载,还有一部分是高通产权的,需要从高通的网站上下载. 将高通产权的代码放到:vendor/qcom/proprietary 1. 设置bms一些参 ...
- 高通 MSM8K bootloader之一: SBL1
MSM8K Boot Flow 转自:http://www.cnblogs.com/liang123/p/6325257.html http://blog.csdn.net/F ...
- linux驱动由浅入深系列:PBL-SBL1-(bootloader)LK-Android启动过程详解之一(高通MSM8953启动实例)
转自:http://blog.csdn.net/radianceblau/article/details/73229005 http://www.aiuxian.com/article/p-14142 ...
随机推荐
- select.select的使用注意事项
1.select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制. 2.select()所维护的存储 ...
- arcgis api for JavaScript _跨域请求
arcgis api for JavaScript 中出现跨域请求是常见问题, 通常出现类似如下错误消息类似: XMLHttpRequest cannot load http://10.32.2.7 ...
- BigDecimal精度与相等比较的坑
先想一下,创建BigDecimal对象的时候一般是怎么创建的? new一个,传进去值 BigDecimal.valueOf方法,传进去值 作为一个数字类型,经常有的操作是比较大小,有一种情况是比较是否 ...
- (转)Spring实现IoC的多种方式
原文地址:http://www.cnblogs.com/best/p/5727935.html 目录 一.使用XML配置的方式实现IOC 二.使用Spring注解配置IOC 三.自动装配 四.零配置实 ...
- 解决SQL Server管理器无法连接远程数据库的问题(转)
add by zhj: 本文最后那个数据库别名没搞明白,在我的测试中没有建别名,是可以的.远程登陆时,服务器名称: 服务器IP,端口号 (如223.42.155.248,52134 如果是默认端口号1 ...
- python框架之Django(2)-简单的CRUD
写一个简单的项目小例子来了解Django中的O/RM操作 前戏 创建app #在Django项目根目录下执行 python3 manage.py startapp [app name] 配置数据库连接 ...
- Catch all the latest Jordan Release Dates
In case y'all missed yesterday's news, Air Jordan 13 Olive 2018 officially unveiled their 2017 Holid ...
- Linux系统——Nginx反向代理与负载均衡
集群集群是指一组(若干个)相互独立的计算机,利用高速通信网路组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运用各自服务的独立服务器.这些服务器之间可以彼此通信,协同向用户提供 ...
- rpm服务的独立服务管理
/etc/init.d 启动脚本的位置 /etc/sysconfig/ 初始化环境配置文件 /etc/ 配置文件位置 /etc/xinetd.conf xinetd配置文件 /etc/xine ...
- matplotlib显示中文
[注意] 可能与本文主题无关,不过我还是想指出来:使用matplotlib库时,下面两种导入方式是等价的(我指的是等效,当然这个说法可以商榷:) import matplotlib.pyplot as ...