简谈高通Trustzone的实现

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两文件

谢谢

时间: 2024-10-14 15:05:43

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

高通智能锁UI显示方案 — 含有简繁体,生僻字,多国外文字库;

对于锁的认知,如果你还停留在机械锁的时代,那你就OUT了,要知道,中国已经步入智能化时代,并且随着人们对锁要求的提高,智能锁的普及率也越来越高.智能锁采用先进技术,个别闪光键盘.锌合金面板:坚固耐用.耐酸腐.更有保姆功能,设置相应时间段.不同于以往"先开启再扫描的方式"的方式,仅需一个动作即可轻松完成指纹扫描. 高通字库芯片支持国标GB18030标准字库,包含27484个简繁体汉字兼容UNICODE,并内置日文.韩文.法文.西班牙文.德文和阿拉伯文等170多国语言字库,功能强大,字型专

浅谈编译高通android5.1源代码

为什么会编译高通5.1源代码,原因很简单,因为公司做高通平台的手机,所以有必要编译下 Linux基础学习篇 1.常用指令 ls 显示文件或目录 –l  列出文件详细信息 l(list)   –a   列出当前目录下所有文件及目录,包括隐藏的a(all) mkdir 创建目录 -p 创建目录,若无父目录,则创建p(parent) cd 切换目录 touch 创建空文件 echo 创建带有内容的文件. cat 查看文件内容 cp 拷贝 mv 移动或重命名 rm 删除文件 -r 递归删除,可删除子目录

Linux进程管理简谈

Linux系统进程管理简谈 进程是什么? 简单来说进程是一个正在执行的程序的一个副本,存在生命周期,有段指令和代码在不断运行. linux内核存储信息的固定格式:task struct 进程的相关信息存储在链表中 多个任务的task struct组件的链表:task list 进程的创建:父进程创建子进程(内核创建init进程,剩余一切进程有init及其子进程进程创建) 父进程创建子进程时向内核调用fork()来创建子进程并且通过调用clone()复制父进程的信息给子进程 Linux进程的优先级

客户端GUI测试技术和自动化测试架构设计简谈

客户端自动化特点 客户端的自动化,通常做过的人都不是很愿意深入讨论.因为除了功能和逻辑之外,不得不面对各种界面变化,各种和环境交互,各种兼容问题以及想不到灰色地带,就算这样,也找不到太多有效的bug.然而即便如此,客户端的自动化必须去做,尤其是GUI的.它的自动化特点是: 复杂 成本高 不容易发现问题 技术要求高 架构很难通用 下面,从一些基本的东西开始一点点的讨论客户端GUI测试的一些问题和处理办法,以及自动化架构设计的一些思路.事实上就像上面说的,GUI的测试并不是为了发现bug,而是回归的

.NET简谈事务、分布式事务处理

在本人的 " .NET简谈事务本质论"一文中我们从整体上了解了事务模型,在我们脑子里能有一个全局的事务处理结构,消除对数据库事务的依赖理解,重新认识事务编程模型. 今天这篇文章我们将使用.NET C#来进行事务性编程,从浅显.简单的本地事务开始,也就是我们用的最多的ADO.NET事务处理,然后我们逐渐扩大事务处理范围,包括对分布式事务处理的使用,多线程事务处理的使用. 数据库事务处理 数据库事务处理我们基本都很熟悉了,begin Transaction --end Transactio

简谈【自动化协议逆向工程技术的当前趋势】

声明: 1)本文由我bitpeach原创撰写,禁止一切形式的转载.如有转载,侵权必究. 2)本简谈主要分为三个方面,第一是自动化协议逆向技术的基本理论,第二是当前发展趋势,第三是入门协议逆向技术的必备过程. 3)既是简谈,则文章篇幅不长,同时本文观点不一定正确,希望抛砖引玉,能得高人指点,幸为殊荣. 4)最近一个月比较忙,昨天正好写完稿子,今天就简写一些内容,避免重复,故为简谈. (一)协议逆向工程理论基础 1.1 什么是协议逆向技术 协议逆向工程是指在不依赖于协议描述的情况下,通过对协议实体的

高通android开发摘要

一部分是开源的.能够从codeaurora.org上下载,另一部分是高通产权的.须要从高通的站点上下载. 将高通产权的代码放到:vendor/qcom/proprietary 1. 设置bms一些參数 @msm-pm8226.dtsi中     pm8226_bms: qcom,bms{        qcom,low-soc-calculate-soc-threshold = <15>; //觉得是低电压的soc(15%)        qcom,low-soc-calculate-soc-

.NET简谈接口

自从面向对象开发方式的出现,抽象的概念就开始日新月异的发展,面向对象编程.面向接口编程.面向组件编程等等:这一系列的概念都是软件工程所追求的思想范畴,高类聚低耦合. 今天我要简谈的是面向对象里面非常重要的也是非常抽象的概念,接口.谈起接口多少人曾经为之痛苦过,尤其是一些刚入门的开发人员(包括小弟),百思不得其解,啥叫接口,接口能干嘛用,用不用有什么区别:等等问题困扰着,这些问题不解决不弄明白,很难在面向对象领域混,更别谈面向对象开发了,可能有人认为面向对象开发就是麻烦我不用一样也能开发,开发一个

中国智能手机步入零增长时代,为何一半国产手机巨头选择为高通站台

25日 高通在北京召开2018高通中国技术与合作峰会,宣布5G领航计划.联想.OPPO.vivo.小米.中兴.闻泰科技在峰会上表示将开启合作,共同加速商用顶级5G终端在2019年的推出. 媒体对此评价为"中国手机半壁江山为高通站台".这样一幕"武林大会"式样的豪华阵容集结,说明了什么? 真的是为了5G布局吗?尤其是在"中国智能手机零增长时代"的大背景下. 一个背靠高通,布局5G,同时试图深入PC的新增长布局,拉开序幕.当然,站台的同时,也有看马戏