mirror of
https://github.com/apache/nuttx-apps.git
synced 2025-07-04 11:04:13 +08:00

Previous version of optee example was using id during shm registration as input whereas it is an output variable. It was also specifying flags to dictate the behaviour whereas the latest implementation of the driver prohibits their use. This commit addresses those issues. Signed-off-by: George Poulios <gpoulios@census-labs.com>
415 lines
9.5 KiB
C
415 lines
9.5 KiB
C
/****************************************************************************
|
|
* apps/examples/optee/optee_main.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/mman.h>
|
|
#include <nuttx/tee.h>
|
|
#include <uuid.h>
|
|
|
|
/****************************************************************************
|
|
* Pre-processor definitions
|
|
****************************************************************************/
|
|
|
|
#undef USE_ALLOC_IOC
|
|
|
|
#ifdef USE_ALLOC_IOC
|
|
# define tee_shm_alloc tee_shm_mmap
|
|
# define tee_shm_free_buf(p, s) munmap(p, s)
|
|
#else
|
|
# define tee_shm_alloc tee_shm_malloc
|
|
# define tee_shm_free_buf(p, s) ((void)s, free(p))
|
|
#endif
|
|
|
|
#define OPTEE_DEV "/dev/tee0"
|
|
|
|
#define PTA_DEVICE_ENUM { 0x7011a688, 0xddde, 0x4053, \
|
|
0xa5, 0xa9, \
|
|
{ 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8 } }
|
|
|
|
#define PTA_CMD_GET_DEVICES 0x0
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
typedef struct tee_shm
|
|
{
|
|
int fd;
|
|
size_t size;
|
|
void *ptr;
|
|
int32_t id;
|
|
} tee_shm_t;
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
static int tee_check_version_and_caps(int fd, uint32_t *caps)
|
|
{
|
|
struct tee_ioctl_version_data ioc_ver;
|
|
int ret;
|
|
|
|
ret = ioctl(fd, TEE_IOC_VERSION, (unsigned long)&ioc_ver);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to query TEE driver version and caps: %d, %s\n",
|
|
ret, strerror(errno));
|
|
return ret;
|
|
}
|
|
|
|
if (ioc_ver.impl_id != TEE_IMPL_ID_OPTEE)
|
|
{
|
|
printf("Not an OP-TEE implementation\n");
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
if (!(ioc_ver.impl_caps & TEE_OPTEE_CAP_TZ))
|
|
{
|
|
printf("OP-TEE TrustZone not supported\n");
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
if (((TEE_GEN_CAP_GP | TEE_GEN_CAP_MEMREF_NULL) & ioc_ver.gen_caps) !=
|
|
(TEE_GEN_CAP_GP | TEE_GEN_CAP_MEMREF_NULL))
|
|
{
|
|
printf("CAP_GP or MEMREF_NULL not supported\n");
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
printf("impl id: %u, impl caps: %u, gen caps: %u\n",
|
|
ioc_ver.impl_id, ioc_ver.impl_caps, ioc_ver.gen_caps);
|
|
|
|
if (caps)
|
|
{
|
|
*caps = ioc_ver.gen_caps;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int tee_open_session(int fd, const uuid_t *uuid, uint32_t *session)
|
|
{
|
|
struct tee_ioctl_open_session_arg ioc_opn;
|
|
struct tee_ioctl_buf_data ioc_buf;
|
|
int ret;
|
|
|
|
memset(&ioc_opn, 0, sizeof(struct tee_ioctl_open_session_arg));
|
|
|
|
uuid_enc_be(&ioc_opn.uuid, uuid);
|
|
|
|
ioc_buf.buf_ptr = (uintptr_t)&ioc_opn;
|
|
ioc_buf.buf_len = sizeof(struct tee_ioctl_open_session_arg);
|
|
|
|
ret = ioctl(fd, TEE_IOC_OPEN_SESSION, (unsigned long)&ioc_buf);
|
|
if (ret < 0)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (session)
|
|
{
|
|
*session = ioc_opn.session;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int tee_invoke(int fd, uint32_t session, uint32_t func,
|
|
struct tee_ioctl_param *params, size_t num_params)
|
|
{
|
|
struct tee_ioctl_invoke_arg *ioc_args;
|
|
struct tee_ioctl_buf_data ioc_buf;
|
|
size_t ioc_args_len;
|
|
int ret;
|
|
|
|
ioc_args_len = sizeof(struct tee_ioctl_invoke_arg) +
|
|
TEE_IOCTL_PARAM_SIZE(num_params);
|
|
|
|
ioc_args = (struct tee_ioctl_invoke_arg *)calloc(1, ioc_args_len);
|
|
if (!ioc_args)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ioc_args->func = func;
|
|
ioc_args->session = session;
|
|
ioc_args->num_params = num_params;
|
|
memcpy(&ioc_args->params, params, TEE_IOCTL_PARAM_SIZE(num_params));
|
|
|
|
ioc_buf.buf_ptr = (uintptr_t)ioc_args;
|
|
ioc_buf.buf_len = ioc_args_len;
|
|
|
|
ret = ioctl(fd, TEE_IOC_INVOKE, (unsigned long)&ioc_buf);
|
|
if (ret < 0)
|
|
{
|
|
goto err_with_args;
|
|
}
|
|
|
|
memcpy(params, &ioc_args->params, TEE_IOCTL_PARAM_SIZE(num_params));
|
|
|
|
err_with_args:
|
|
free(ioc_args);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int tee_shm_register(int fd, tee_shm_t *shm)
|
|
{
|
|
struct tee_ioctl_shm_register_data ioc_reg;
|
|
|
|
memset(&ioc_reg, 0, sizeof(struct tee_ioctl_shm_register_data));
|
|
|
|
if (!shm)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
ioc_reg.addr = (uintptr_t)shm->ptr;
|
|
ioc_reg.length = shm->size;
|
|
|
|
shm->fd = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg);
|
|
shm->id = ioc_reg.id;
|
|
|
|
return shm->fd < 0 ? shm->fd : 0;
|
|
}
|
|
|
|
#ifdef USE_ALLOC_IOC
|
|
static int tee_shm_mmap(int fd, tee_shm_t *shm, bool reg)
|
|
{
|
|
struct tee_ioctl_shm_alloc_data ioc_alloc;
|
|
int ret = 0;
|
|
|
|
memset(&ioc_alloc, 0, sizeof(struct tee_ioctl_shm_alloc_data));
|
|
|
|
if (!shm)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
ioc_alloc.size = shm->size;
|
|
|
|
shm->fd = ioctl(fd, TEE_IOC_SHM_ALLOC, (unsigned long)&ioc_alloc);
|
|
if (shm->fd < 0)
|
|
{
|
|
return shm->fd;
|
|
}
|
|
|
|
shm->ptr = mmap(NULL, shm->size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
|
shm->fd, 0);
|
|
if (shm->ptr == MAP_FAILED)
|
|
{
|
|
close(shm->fd);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (reg)
|
|
{
|
|
ret = tee_shm_register(fd, shm);
|
|
if (ret < 0)
|
|
{
|
|
munmap(shm->ptr, shm->size);
|
|
close(shm->fd);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#else /* !USE_ALLOC_IOC */
|
|
static int tee_shm_malloc(int fd, tee_shm_t *shm, bool reg)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (!shm)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
shm->ptr = malloc(shm->size);
|
|
if (!shm->ptr)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
shm->fd = -1;
|
|
|
|
if (reg)
|
|
{
|
|
ret = tee_shm_register(fd, shm);
|
|
if (ret < 0)
|
|
{
|
|
free(shm->ptr);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif /* !USE_ALLOC_IOC */
|
|
|
|
static void tee_shm_free(tee_shm_t *shm)
|
|
{
|
|
if (!shm)
|
|
{
|
|
return;
|
|
}
|
|
|
|
tee_shm_free_buf(shm->ptr, shm->size);
|
|
|
|
if (shm->fd >= 0)
|
|
{
|
|
close(shm->fd);
|
|
}
|
|
|
|
shm->ptr = NULL;
|
|
shm->fd = -1;
|
|
}
|
|
|
|
static int tee_close_session(int fd, uint32_t session)
|
|
{
|
|
struct tee_ioctl_close_session_arg ioc_close;
|
|
int ret;
|
|
|
|
ioc_close.session = session;
|
|
|
|
ret = ioctl(fd, TEE_IOC_CLOSE_SESSION, (unsigned long)&ioc_close);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* optee_main
|
|
****************************************************************************/
|
|
|
|
int main(int argc, FAR char *argv[])
|
|
{
|
|
int fd;
|
|
uint32_t caps;
|
|
const uuid_t pta_dvc_uuid = PTA_DEVICE_ENUM;
|
|
uint32_t session;
|
|
struct tee_ioctl_param par0;
|
|
tee_shm_t shm;
|
|
unsigned int count;
|
|
const uuid_t *raw_ta_uuid;
|
|
uuid_t ta_uuid;
|
|
char *ta_uuid_s;
|
|
int ret;
|
|
|
|
memset(&par0, 0, sizeof(struct tee_ioctl_param));
|
|
memset(&shm, 0, sizeof(tee_shm_t));
|
|
|
|
fd = open(OPTEE_DEV, O_RDONLY | O_NONBLOCK);
|
|
if (fd < 0)
|
|
{
|
|
printf("Failed to open " OPTEE_DEV ": %s\n", strerror(errno));
|
|
return -errno;
|
|
}
|
|
|
|
ret = tee_check_version_and_caps(fd, &caps);
|
|
if (ret < 0)
|
|
{
|
|
goto err;
|
|
}
|
|
|
|
ret = tee_open_session(fd, &pta_dvc_uuid, &session);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to open session with devices.pta: %d, %s\n",
|
|
ret, strerror(errno));
|
|
goto err;
|
|
}
|
|
|
|
par0.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
|
|
par0.c = TEE_MEMREF_NULL;
|
|
|
|
ret = tee_invoke(fd, session, PTA_CMD_GET_DEVICES, &par0, 1);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to get size needed for device enumeration: %d, %s\n",
|
|
ret, strerror(errno));
|
|
goto err_with_session;
|
|
}
|
|
|
|
shm.size = par0.b;
|
|
|
|
ret = tee_shm_alloc(fd, &shm, caps & TEE_GEN_CAP_REG_MEM);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to allocate shared memory: %d, %s\n",
|
|
ret, strerror(errno));
|
|
goto err_with_session;
|
|
}
|
|
|
|
par0.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
|
|
par0.a = 0;
|
|
par0.b = shm.size;
|
|
par0.c = shm.id;
|
|
|
|
ret = tee_invoke(fd, session, PTA_CMD_GET_DEVICES, &par0, 1);
|
|
if (ret < 0)
|
|
{
|
|
printf("Failed to enumerate devices: %d, %s\n", ret, strerror(errno));
|
|
goto err_with_shm;
|
|
}
|
|
|
|
printf("Available devices:\n");
|
|
|
|
count = par0.b / sizeof(uuid_t);
|
|
raw_ta_uuid = (uuid_t *)shm.ptr;
|
|
|
|
while (count--)
|
|
{
|
|
uuid_dec_be(raw_ta_uuid, &ta_uuid);
|
|
uuid_to_string(&ta_uuid, &ta_uuid_s, NULL);
|
|
|
|
printf(" %s\n", ta_uuid_s);
|
|
|
|
free(ta_uuid_s);
|
|
raw_ta_uuid++;
|
|
}
|
|
|
|
err_with_shm:
|
|
tee_shm_free(&shm);
|
|
|
|
err_with_session:
|
|
tee_close_session(fd, session);
|
|
|
|
err:
|
|
close(fd);
|
|
|
|
return ret;
|
|
}
|