当前位置:   article > 正文

OP-TEE TA:读写寄存器数据_optee ta使用i2c

optee ta使用i2c

最近想为OP-TEE的Trusted OS开发一个触摸屏驱动,在查询代码的时候发现直接调用TA修改TZPC寄存器的值是不可行的,原因是user TA的运行采用了沙盒机制,所以无法直接访问寄存器所映射的物理地址。所以在查看了相关资料后,总结出如下方法用以解决此问题。

一. 编写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> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里比较重要的是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 */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

首先需要定义此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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

读寄存器和写寄存器的相关方法实现。
其他方法:

/*
 * 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

这些方法为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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

将此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
  • 1
  • 2

二.将寄存器的映射地址添加到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. */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

更新:OP-TEE 2.0及以上版本,使用register_phys_mem(…)控制可访问的地址空间,其中MEM_AREA_IO_NSEC参数下的地址空间,普通世界可通过STATIC TA访问,MEN_AREA_IO_SEC参数下的地址空间,只可以由安全世界访问。


笔者使用上一篇博客中提到的Helloworld.ta作为调用读写寄存器的static TA的user TA,编译和移植方法已经讲过了,不再累述。

首先在soc中运行xtest 1001检测static TA是否可用。
若运行成功结果如下图:
xtest 1001
注意:若出现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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

测试成功后,编写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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

最后可在soc上运行普通TA调用静态TA,将显示UART寄存器的值。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/129994
推荐阅读
相关标签
  

闽ICP备14008679号