OP-TEE TA:读写寄存器数据
2016-04-27 15:49
447 查看
最近想为OP-TEE的Trusted OS开发一个触摸屏驱动,在查询代码的时候发现直接调用TA修改TZPC寄存器的值是不可行的,原因是user TA的运行采用了沙盒机制,所以无法直接访问寄存器所映射的物理地址。所以在查看了相关资料后,总结出如下方法用以解决此问题。
首先是头文件:
这里比较重要的是statci_ta.h和io.h,前一个头文件定义了static TA的相关函数和宏定义,后一个给出了读写寄存器物理地址中所存储的值的方法。
宏定义:
首先需要定义此TA的名字和对应的UUID值(此值用于user TA建立会话的时候使用),其次设置两个状态值,分别对应寄存器的读写操作,最后设置你要读取的寄存器的映射地址。(笔者这里使用的是HIKEY的UART寄存器的映射地址)
操作方法:
读寄存器和写寄存器的相关方法实现。
其他方法:
这些方法为static TA的其他方法,由于在此功能实现中未曾用到,故都为最简实现。
将此static TA所定义的内容提交到Trusted Core中。
最后修改/sta目录下的sub.mk文件,将新建的static TA文件sta_reg.c添加到编译序列中。
首先在soc中运行xtest 1001检测static TA是否可用。
若运行成功结果如下图:
注意:若出现TA查找不到的错误,说明此soc中未设置static TA的相关flag,解决办法如下:
修改此soc的conf.mk文件,将未设置的flag添加进去:
测试成功后,编写user TA的host部分代码,用以调用static TA,代码如下:
最后可在soc上运行helloworld,将显示UART寄存器的值。
一. 编写static TA
在/optee_os/core/arch/arm/sta目录下新建一个sta_reg.c文件,作为一个新的static TA,具体代码如下,此文件结构参照static TA的例程程序stats.c,此文件稍微有点长,我们分段解释一下。首先是头文件:
#include <compiler.h> #include <stdio.h> #include <trace.h> #include <kernel/static_ta.h> #include <string.h> #include <string_ext.h> #include <io.h>
这里比较重要的是statci_ta.h和io.h,前一个头文件定义了static TA的相关函数和宏定义,后一个给出了读写寄存器物理地址中所存储的值的方法。
宏定义:
#define TA_NAME "sta_reg.ta" #define STA_REG_UUID \ { 0xd96a5b40, 0x12c7, 0x21af, \ { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } #define STA_READ_STATS 0 #define STA_WRITE_STATS 1 #define CONSOLE_UART_BASE 0xF8015000 #define UART_IBRD 0x24 /* integer baud register */
首先需要定义此TA的名字和对应的UUID值(此值用于user TA建立会话的时候使用),其次设置两个状态值,分别对应寄存器的读写操作,最后设置你要读取的寄存器的映射地址。(笔者这里使用的是HIKEY的UART寄存器的映射地址)
操作方法:
static TEE_Result read_regs(uint32_t type __unused, TEE_Param p[4] __unused) { EMSG("UART: 0x%x\n",read32(CONSOLE_UART_BASE+UART_IBRD)); return TEE_SUCCESS; } static TEE_Result write_regs(uint32_t type __unused, TEE_Param p[4] __unused) { return TEE_SUCCESS; }
读寄存器和写寄存器的相关方法实现。
其他方法:
/* * Trusted Application Entry Points */ static TEE_Result create_ta(void) { return TEE_SUCCESS; } static void destroy_ta(void) { } static TEE_Result open_session(uint32_t ptype __unused, TEE_Param params[4] __unused, void **ppsess __unused) { return TEE_SUCCESS; } static void close_session(void *psess __unused) { } static TEE_Result invoke_command(void *psess __unused, uint32_t cmd, uint32_t ptypes, TEE_Param params[4]) { switch (cmd) { case STA_READ_STATS: return read_regs(ptypes, params); case STA_WRITE_STATS: return write_regs(ptypes, params); default: break; } return TEE_ERROR_BAD_PARAMETERS; }
这些方法为static TA的其他方法,由于在此功能实现中未曾用到,故都为最简实现。
static_ta_register(.uuid = STA_REG_UUID, .name = TA_NAME, .create_entry_point = create_ta, .destroy_entry_point = destroy_ta, .open_session_entry_point = open_session, .close_session_entry_point = close_session, .invoke_command_entry_point = invoke_command);
将此static TA所定义的内容提交到Trusted Core中。
最后修改/sta目录下的sub.mk文件,将新建的static TA文件sta_reg.c添加到编译序列中。
srcs-$(CFG_WITH_STATS) += stats.c +srcs-$(CFG_WITH_STATS) += sta_reg.c
二.将寄存器的映射地址添加到core_map中
修改optee_os/core/arch/arm/kernel/generic_core_bootcfg.c文件,添加一个可映射的地址,用于static TA的访问。/* Platform-specific memory layout provided to TEE core. */ static struct map_area bootcfg_memory_map[] = { +/* TZPC core exec */ +{ + .type = MEM_AREA_IO_SEC, + .pa = 0xF8015000, .size = 0x400000, + .cached = true, .secure = true, .rw = true, .exec = false, +}, /* TEE core execution RAM. */
三.使用user TA与static TA建立会话
笔者使用上一篇博客中提到的Helloworld.ta作为调用读写寄存器的static TA的user TA,编译和移植方法已经讲过了,不再累述。首先在soc中运行xtest 1001检测static TA是否可用。
若运行成功结果如下图:
注意:若出现TA查找不到的错误,说明此soc中未设置static TA的相关flag,解决办法如下:
修改此soc的conf.mk文件,将未设置的flag添加进去:
endif +CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_TEE_FS_KEY_MANAGER_TEST ?= y +CFG_WITH_STACK_CANARIES ?= y +CFG_WITH_STATS ?= y CFG_CRYPTO_WITH_CE ?= y
测试成功后,编写user TA的host部分代码,用以调用static TA,代码如下:
#include <stdio.h> #include <err.h> #include <tee_client_api.h> #include <ta_hello_world.h> #define STA_REG_UUID \ { 0xd96a5b40, 0x12c7, 0x21af, \ { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } int main(int argc, char *argv[]) { TEEC_Context hello_teec_ctx; TEEC_Result res; TEEC_Session session = { 0 }; TEEC_UUID uuid = STA_REG_UUID; uint32_t ret_orig; /* Initialize a context connecting us to the TEE */ res = TEEC_InitializeContext(NULL, &hello_teec_ctx); if (res != TEEC_SUCCESS) errx(1, "TEEC_InitializeContext failed with code 0x%x", res); /* * Open a session to the "hello world" TA, the TA will print "hello * world!" in the log when the session is created. */ res = TEEC_OpenSession(&hello_teec_ctx, &session, &uuid, TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig); if (res != TEEC_SUCCESS) errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x", res, ret_orig); /* * Execute a function in the TA by invoking it, in this case * we're incrementing a number. * * The value of command ID part and how the parameters are * interpreted is part of the interface provided by the TA. */ /* * Prepare the argument. Pass a value in the first parameter, * the remaining three parameters are unused. */ printf("Invoking TA to increment !\n"); res = TEEC_InvokeCommand(&session, 0, NULL, &ret_orig); if (res != TEEC_SUCCESS) errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x", res, ret_orig); printf("test static TA\n"); /* * We're done with the TA, close the session and * destroy the context. * * The TA will print "Goodbye!" in the log when the * session is closed. */ TEEC_CloseSession(&session); TEEC_FinalizeContext(&hello_teec_ctx); return 0; }
最后可在soc上运行helloworld,将显示UART寄存器的值。
相关文章推荐
- 阿里云安装docker的问题
- [企业级linux安全管理]- 主机安全管理
- Linux下安装Activemq-5.11.1
- Auto packing the repository in background for optimum performance
- [企业级linux安全管理]- 系统日志管理
- Android系统启动流程 -- linux kernel
- win7 vm10.0 centos7 共享目录问题
- [企业级linux安全管理]- 安全管理基础(1)
- Linux命令常用速查(自用)
- Linux驱动常用知识小结
- 【Linux】Red Hat Linux在虚拟机安装指南
- vi 普通操作 linux
- 让shell脚本在后台运行的两种方法
- linux私房菜学习笔记—vim编辑器
- html5手机网站需要加的那些meta/link标签,html5 meta全解
- linux系统下要删除非空目录
- OpenGL与OpenCV实现增强现实
- linux常用命令详解
- centos7之lnmp安装
- linux系统下修改文件夹权限及其子文件夹权限