This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit a2a689fee046d2bdb14e4f6feba8d82cc9de9040
Author: George Poulios <gpoul...@census-labs.com>
AuthorDate: Sat May 10 14:40:26 2025 +0300

    drivers/misc/optee: Fix GP API compatibility
    
    Previous implementation was not compatible with GlobalPlatform
    API in the following ways:
     - Registered mem IDs would begin from negatives when it should
       have been greater than or equal to 0
     - Register IOCTL would return 0 on success, when it should have
       been returning a file descriptor.
     - Register IOCTL would expect the user-space client to specify
       TEE_SHM_* flags dictating its behaviour when in fact, libteec
       never specifies flags.
    
    This commit fixes all those issues. It uses nuttx/idr.h instead
    of a linked list, and it uses `file_allocate` to provide file
    descriptors for registered shared memory. Upon close(fd), the
    memory is de-registered and freed accordingly. It also updates
    the documentation accordingly.
    
    Signed-off-by: George Poulios <gpoul...@census-labs.com>
---
 Documentation/guides/optee.rst |  46 +++---
 drivers/misc/optee.c           | 325 ++++++++++++++++++++++++-----------------
 drivers/misc/optee.h           |  22 +--
 drivers/misc/optee_smc.c       |   7 +-
 include/nuttx/tee.h            |   8 +-
 5 files changed, 234 insertions(+), 174 deletions(-)

diff --git a/Documentation/guides/optee.rst b/Documentation/guides/optee.rst
index e133d9387a..ab1adac9b3 100644
--- a/Documentation/guides/optee.rst
+++ b/Documentation/guides/optee.rst
@@ -100,8 +100,8 @@ on success unless otherwise specified (see 
``TEE_IOC_SHM_ALLOC``).
     future, but until then, please refer to ``include/nuttx/tee.h`` for 
details.
     In short, for shared memory references, ``.a`` is the offset into the
     shared memory buffer, ``.b`` is the size of the buffer, and ``.c`` is the
-    the shared memory identifier (``.addr`` field used in
-    ``TEE_IOC_SHM_REGISTER``).
+    the shared memory identifier (``.id`` field returned by
+    ``TEE_IOC_SHM_ALLOC`` or ``TEE_IOC_SHM_REGISTER``).
 
 - ``TEE_IOC_CANCEL`` : Cancel a currently invoked command.
 
@@ -113,8 +113,8 @@ on success unless otherwise specified (see 
``TEE_IOC_SHM_ALLOC``).
   - Expects a ``struct tee_ioctl_shm_alloc_data`` pointer with the ``.size``
     field set, and ignoring the ``.flags`` field. Upon successful return,
     it returns the memory file descriptor one can use ``mmap()`` on (with
-    ``MAP_SHARED``). It also returns an identifier for the allocation
-    in ``.id``.
+    ``MAP_SHARED``). It also returns an identifier for use in memory references
+    (``tee_ioctl_param.c`` field) in ``.id``.
 
 - ``TEE_IOC_SHM_REGISTER`` : Register a shared memory reference with the 
secure OS.
 
@@ -126,10 +126,9 @@ on success unless otherwise specified (see 
``TEE_IOC_SHM_ALLOC``).
     ``TEE_SHM_SEC_REGISTER`` registers the memory with the secure OS for later
     use in memrefs and is automatically de-registered during driver close if
     ``TEE_SHM_REGISTER`` is also specified. ``.addr`` shall point to the (user)
-    memory to register and ``.size`` shall indicate its size. The identifier
-    used to register shared memory with the secure OS is the value of the
-    ``.addr`` field (what one needs to specify in ``tee_ioctl_param.c``
-    during a ``TEE_IOC_INVOKE``).
+    memory to register and ``.size`` shall indicate its size. One may use the
+    returned ``.id`` field when specifying shared memory references
+    (``tee_ioctl_param.c`` field).
 
 Typical usage
 =============
@@ -167,7 +166,7 @@ Typical usage
          return ret;
        }
 
-     [...check ioc_ver accordingly...]
+     /* check ioc_ver accordingly */
 
 #. Open a session with a Trusted Application
 
@@ -188,7 +187,7 @@ Typical usage
          return ret;
        }
 
-     [...use ioc_opn.session returned...]
+     /* use ioc_opn.session returned */
 
 #. Invoke a function of the Trusted Application
 
@@ -222,7 +221,7 @@ Typical usage
          goto err_with_args;
        }
 
-     [...use result (if any) in ioc_args->params...]
+     /* use result (if any) in ioc_args->params */
 
 #. Allocate shared memory through the driver
 
@@ -253,22 +252,25 @@ Typical usage
    .. code-block:: c
 
      /* The following will fail if TEE_GEN_CAP_REG_MEM is not reported in
-      * the returned `ioc_ver.gen_caps` in step 1 above */
+      * the returned `ioc_ver.gen_caps` in step 1 above
+      * Note: user memory used does not have to be allocated through IOCTL
+      */
 
      struct tee_ioctl_shm_register_data ioc_reg = { 0 };
 
-     ioc_reg.addr = (uintptr_t)ptr;
-     ioc_reg.length = ioc_alloc.size;
-     ioc_reg.flags = TEE_SHM_REGISTER | TEE_SHM_SEC_REGISTER;
+     ioc_reg.addr = (uintptr_t)<some user memory ptr>;
+     ioc_reg.length = <user memory size>;
 
-     ret = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg);
-     if (ret < 0)
+     memfd = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg);
+     if (memfd < 0)
        {
-         munmap(shm, ioc_alloc.size);
-         close(memfd);
          return ret;
        }
 
+     /* use ioc_reg.id returned in OP-TEE parameters (e.g. open, invoke) */
+
+     close(memfd);
+
 #. Use the registered shared memory in an invocation
 
    .. code-block:: c
@@ -292,8 +294,8 @@ Typical usage
      ioc_args->num_params = num_params;
      ioc_args->params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
      ioc_args->params[0].a = 0;
-     ioc_args->params[0].b = ioc_alloc.size;
-     ioc_args->params[0].a = (uintptr_t)shm;
+     ioc_args->params[0].b = ioc_reg.length;
+     ioc_args->params[0].c = ioc_reg.id;
 
      ioc_buf.buf_ptr = (uintptr_t)ioc_args;
      ioc_buf.buf_len = ioc_args_len;
@@ -304,4 +306,4 @@ Typical usage
          goto err_with_args;
        }
 
-     [...use result (if any) in ioc_args->params...]
+     /* use result (if any) in ioc_args->params */
diff --git a/drivers/misc/optee.c b/drivers/misc/optee.c
index 5ec64ad049..e67854965a 100644
--- a/drivers/misc/optee.c
+++ b/drivers/misc/optee.c
@@ -144,6 +144,8 @@ static int optee_close(FAR struct file *filep);
 static int optee_ioctl(FAR struct file *filep, int cmd,
                        unsigned long arg);
 
+static int optee_shm_close(FAR struct file *filep);
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -152,15 +154,35 @@ static int optee_ioctl(FAR struct file *filep, int cmd,
 
 static const struct file_operations g_optee_ops =
 {
-  optee_open,     /* open */
-  optee_close,    /* close */
-  NULL,           /* read */
-  NULL,           /* write */
-  NULL,           /* seek */
-  optee_ioctl,    /* ioctl */
-  NULL,           /* mmap */
-  NULL,           /* truncate */
-  NULL            /* poll */
+  optee_open,      /* open */
+  optee_close,     /* close */
+  NULL,            /* read */
+  NULL,            /* write */
+  NULL,            /* seek */
+  optee_ioctl,     /* ioctl */
+  NULL,            /* mmap */
+  NULL,            /* truncate */
+  NULL             /* poll */
+};
+
+static const struct file_operations g_optee_shm_ops =
+{
+  NULL,            /* open */
+  optee_shm_close, /* close */
+  NULL,            /* read */
+  NULL,            /* write */
+  NULL,            /* seek */
+  NULL,            /* ioctl */
+  NULL,            /* mmap */
+  NULL,            /* truncate */
+  NULL             /* poll */
+};
+
+static struct inode g_optee_shm_inode =
+{
+  .i_flags = FSNODEFLAG_TYPE_SHM, /* could also be DRIVER; doesn't matter */
+  .i_crefs = 1,                   /* inode never to be released */
+  .u.i_ops = &g_optee_shm_ops
 };
 
 /****************************************************************************
@@ -246,41 +268,6 @@ static bool optee_is_valid_range(FAR const void *va, 
size_t size)
 #  define optee_is_valid_range(addr, size) (true)
 #endif
 
-/****************************************************************************
- * Name: optee_shm_next_id
- *
- * Description:
- *   Return a unique ID for adding a new entry to the list of shared memory
- *   chunks registered with the driver. This function assumes all new items
- *   in the list are added to the head. It is NOT thread-safe.
- *
- * Parameters:
- *   priv  - The driver's private data structure
- *
- * Returned Values:
- *   A unique ID for the next shared memory list entry to be added.
- *
- ****************************************************************************/
-
-static inline int32_t optee_shm_next_id(FAR struct optee_priv_data *priv)
-{
-  FAR struct optee_shm_entry *shme;
-  int32_t next_id;
-
-  if (list_is_empty(&priv->shm_list))
-    {
-      next_id = INT32_MIN;
-    }
-  else
-    {
-      shme = list_first_entry(&priv->shm_list, struct optee_shm_entry,
-                              node);
-      next_id = shme->shm.id + 1;
-    }
-
-  return next_id;
-}
-
 /****************************************************************************
  * Name: optee_shm_to_page_list
  *
@@ -323,8 +310,8 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
   uint32_t list_size;
   uint32_t i = 0;
 
-  pgoff = shme->shm.addr & (pgsize - 1);
-  total_pages = (uint32_t)div_round_up(pgoff + shme->shm.length, pgsize);
+  pgoff = shme->addr & (pgsize - 1);
+  total_pages = (uint32_t)div_round_up(pgoff + shme->length, pgsize);
   list_size = div_round_up(total_pages, OPTEE_PAGES_ARRAY_LEN)
               * sizeof(struct optee_page_list_entry);
 
@@ -340,7 +327,7 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
     }
 
   list_entry = (FAR struct optee_page_list_entry *)list;
-  page = ALIGN_DOWN(shme->shm.addr, pgsize);
+  page = ALIGN_DOWN(shme->addr, pgsize);
   while (total_pages)
     {
       list_entry->pages_array[i++] = optee_va_to_pa((FAR const void *)page);
@@ -364,7 +351,7 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
 }
 
 /****************************************************************************
- * Name: optee_shm_sec_register
+ * Name: optee_shm_register
  *
  * Description:
  *   Register specified shared memory entry with OP-TEE.
@@ -380,8 +367,8 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme,
  *
  ****************************************************************************/
 
-static int optee_shm_sec_register(FAR struct optee_priv_data *priv,
-                                  FAR struct optee_shm_entry *shme)
+static int optee_shm_register(FAR struct optee_priv_data *priv,
+                              FAR struct optee_shm_entry *shme)
 {
   FAR struct optee_msg_arg *msg;
   uintptr_t page_list_pa;
@@ -404,8 +391,8 @@ static int optee_shm_sec_register(FAR struct 
optee_priv_data *priv,
   msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
                         OPTEE_MSG_ATTR_NONCONTIG;
   msg->params[0].u.tmem.buf_ptr = page_list_pa;
-  msg->params[0].u.tmem.shm_ref = shme->shm.addr;
-  msg->params[0].u.tmem.size = shme->shm.length;
+  msg->params[0].u.tmem.shm_ref = (uintptr_t)shme;
+  msg->params[0].u.tmem.size = shme->length;
 
   ret = optee_transport_call(priv, msg);
   if (ret < 0)
@@ -426,7 +413,7 @@ errout_with_msg:
 }
 
 /****************************************************************************
- * Name: optee_shm_sec_unregister
+ * Name: optee_shm_unregister
  *
  * Description:
  *   Unregister specified shared memory entry with OP-TEE.
@@ -442,8 +429,8 @@ errout_with_msg:
  *
  ****************************************************************************/
 
-static int optee_shm_sec_unregister(FAR struct optee_priv_data *priv,
-                                    FAR struct optee_shm_entry *shme)
+static int optee_shm_unregister(FAR struct optee_priv_data *priv,
+                                FAR struct optee_shm_entry *shme)
 {
   FAR struct optee_msg_arg *msg;
   int ret = 0;
@@ -456,7 +443,7 @@ static int optee_shm_sec_unregister(FAR struct 
optee_priv_data *priv,
 
   msg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
   msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
-  msg->params[0].u.rmem.shm_ref = shme->shm.addr;
+  msg->params[0].u.rmem.shm_ref = (uintptr_t)shme;
 
   ret = optee_transport_call(priv, msg);
   if (ret < 0)
@@ -474,6 +461,29 @@ errout_with_msg:
   return ret;
 }
 
+/****************************************************************************
+ * Name: optee_shm_close
+ *
+ * Description:
+ *   shm close operation
+ *
+ * Parameters:
+ *   filep  - the file instance
+ *
+ * Returned Values:
+ *   Always OK.
+ *
+ ****************************************************************************/
+
+static int optee_shm_close(FAR struct file *filep)
+{
+  FAR struct optee_shm_entry *shme = filep->f_priv;
+
+  optee_shm_free(shme);
+  filep->f_priv = NULL;
+  return 0;
+}
+
 /****************************************************************************
  * Name: optee_open
  *
@@ -499,8 +509,7 @@ static int optee_open(FAR struct file *filep)
       return ret;
     }
 
-  list_initialize(&priv->shm_list);
-  spin_lock_init(&priv->lock);
+  priv->shms = idr_init();
   filep->f_priv = priv;
   return 0;
 }
@@ -515,7 +524,7 @@ static int optee_open(FAR struct file *filep)
  *   filep  - the file instance
  *
  * Returned Values:
- *   OK on success; A negated errno value is returned on any failure.
+ *   Always OK.
  *
  ****************************************************************************/
 
@@ -523,23 +532,75 @@ static int optee_close(FAR struct file *filep)
 {
   FAR struct optee_priv_data *priv = filep->f_priv;
   FAR struct optee_shm_entry *shme;
-  FAR struct optee_shm_entry *tmp;
+  int id = 0;
 
-  list_for_every_entry_safe(&priv->shm_list, shme, tmp,
-                            struct optee_shm_entry, node)
+  idr_for_each_entry(priv->shms, shme, id)
     {
-      optee_shm_free(priv, shme);
+      optee_shm_free(shme);
     }
 
+  idr_destroy(priv->shms);
   optee_transport_close(priv);
   return 0;
 }
 
-static int optee_to_msg_param(FAR struct optee_msg_param *mparams,
+static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv,
+                                     FAR struct optee_msg_param *mp,
+                                     FAR const struct tee_ioctl_param *p)
+{
+  FAR struct optee_shm_entry *shme;
+
+  /* Warning: the case for non-registered memrefs below is a hack to work
+   * with openvela. Normally, non-registered memory should be specified as
+   * OPTEE_MSG_ATTR_TYPE_TMEM_* (note the 'T') and `buf_ptr` should be set
+   * to the physical address of buffer.
+   *
+   * Related openvela patches:
+   *  - external_optee_optee_os@1a29df42 core/tee/entry_std.c#L160
+   *  - frameworks_security_optee_vela@54b377d5c compat/mobj_dyn_shm.c#L25
+   *
+   * Ideally, in the future, this should be wrapped around some
+   * CONFIG_OPTEE_OPENVELA_COMPAT guard.
+   */
+
+  mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
+             TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+  if (p->c != TEE_MEMREF_NULL)
+    {
+      shme = idr_find(priv->shms, p->c);
+      if (shme == NULL)
+        {
+          return -EINVAL;
+        }
+
+      if (shme->flags & TEE_SHM_REGISTER)
+        {
+          mp->u.rmem.shm_ref = (uintptr_t)shme;
+        }
+      else
+        {
+          /* hack to comply with openvela */
+
+          mp->u.rmem.shm_ref = shme->addr;
+        }
+    }
+  else
+    {
+      mp->u.rmem.shm_ref = 0;
+    }
+
+  mp->u.rmem.size = p->b;
+  mp->u.rmem.offs = p->a;
+  return 0;
+}
+
+static int optee_to_msg_param(FAR struct optee_priv_data *priv,
+                              FAR struct optee_msg_param *mparams,
                               size_t num_params,
                               FAR const struct tee_ioctl_param *params)
 {
   size_t n;
+  int ret;
 
   for (n = 0; n < num_params; n++)
     {
@@ -568,19 +629,11 @@ static int optee_to_msg_param(FAR struct optee_msg_param 
*mparams,
           case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
           case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
           case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
-            mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
-                       TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
-             if (p->c != TEE_MEMREF_NULL)
-              {
-                mp->u.rmem.shm_ref = p->c;
-              }
-            else
+            ret = optee_memref_to_msg_param(priv, mp, p);
+            if (ret < 0)
               {
-                mp->u.rmem.shm_ref = 0;
+                return ret;
               }
-
-            mp->u.rmem.size = p->b;
-            mp->u.rmem.offs = p->a;
             break;
           default:
             return -EINVAL;
@@ -719,7 +772,8 @@ static int optee_ioctl_open_session(FAR struct 
optee_priv_data *priv,
   memcpy(&msg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
   msg->params[1].u.value.c = arg->clnt_login;
 
-  ret = optee_to_msg_param(msg->params + 2, arg->num_params, arg->params);
+  ret = optee_to_msg_param(priv, msg->params + 2, arg->num_params,
+                           arg->params);
   if (ret < 0)
     {
       goto errout_with_msg;
@@ -731,8 +785,7 @@ static int optee_ioctl_open_session(FAR struct 
optee_priv_data *priv,
       goto errout_with_msg;
     }
 
-  ret = optee_from_msg_param(arg->params, arg->num_params,
-                             msg->params + 2);
+  ret = optee_from_msg_param(arg->params, arg->num_params, msg->params + 2);
   if (ret < 0)
     {
       optee_close_session(priv, msg->session);
@@ -798,7 +851,7 @@ static int optee_ioctl_invoke(FAR struct optee_priv_data 
*priv,
   msg->session = arg->session;
   msg->cancel_id = arg->cancel_id;
 
-  ret = optee_to_msg_param(msg->params, arg->num_params, arg->params);
+  ret = optee_to_msg_param(priv, msg->params, arg->num_params, arg->params);
   if (ret < 0)
     {
       goto errout_with_msg;
@@ -873,9 +926,13 @@ static int optee_ioctl_cancel(FAR struct optee_priv_data 
*priv,
 }
 
 static int
-optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data *data)
+optee_ioctl_shm_alloc(FAR struct optee_priv_data *priv,
+                      FAR struct tee_ioctl_shm_alloc_data *data)
 {
+  FAR struct optee_shm_entry *shme;
+  FAR void *addr;
   int memfd;
+  int ret;
 
   if (!optee_is_valid_range(data, sizeof(*data)))
     {
@@ -890,21 +947,32 @@ optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data 
*data)
 
   if (ftruncate(memfd, data->size) < 0)
     {
+      ret = get_errno();
       goto err;
     }
 
-  data->id = (uintptr_t)mmap(NULL, data->size, PROT_READ | PROT_WRITE,
-                             MAP_SHARED, memfd, 0);
-  if (data->id == (uintptr_t)MAP_FAILED)
+  addr = mmap(NULL, data->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+              memfd, 0);
+  if (addr == MAP_FAILED)
     {
+      ret = get_errno();
       goto err;
     }
 
+  ret = optee_shm_alloc(priv, addr, data->size, 0, &shme);
+  if (ret < 0)
+    {
+      goto err_with_mmap;
+    }
+
+  data->id = shme->id;
   return memfd;
 
+err_with_mmap:
+  munmap(addr, data->size);
 err:
   close(memfd);
-  return get_errno();
+  return ret;
 }
 
 static int
@@ -925,20 +993,27 @@ optee_ioctl_shm_register(FAR struct optee_priv_data *priv,
       return -EFAULT;
     }
 
-  if (rdata->flags & TEE_SHM_ALLOC)
+  if (rdata->flags)
     {
       return -EINVAL;
     }
 
   ret = optee_shm_alloc(priv, (FAR void *)(uintptr_t)rdata->addr,
-                        rdata->length, rdata->flags, &shme);
-  if (ret)
+                        rdata->length, TEE_SHM_REGISTER, &shme);
+  if (ret < 0)
     {
       return ret;
     }
 
-  rdata->id = shme->shm.id;
-  return 0;
+  ret = file_allocate(&g_optee_shm_inode, O_CLOEXEC, 0, shme, 0, true);
+  if (ret < 0)
+    {
+      optee_shm_free(shme);
+      return ret;
+    }
+
+  rdata->id = shme->id;
+  return ret;
 }
 
 /****************************************************************************
@@ -975,7 +1050,7 @@ static int optee_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
       case TEE_IOC_CANCEL:
         return optee_ioctl_cancel(priv, parg);
       case TEE_IOC_SHM_ALLOC:
-        return optee_ioctl_shm_alloc(parg);
+        return optee_ioctl_shm_alloc(priv, parg);
       case TEE_IOC_SHM_REGISTER:
         return optee_ioctl_shm_register(priv, parg);
       default:
@@ -1031,7 +1106,7 @@ uintptr_t optee_va_to_pa(FAR const void *va)
  * Name: optee_shm_alloc
  *
  * Description:
- *   Allocate, register and/or add shared memory for use with OP-TEE calls.
+ *   Allocate and/or register shared memory with the OP-TEE OS.
  *   Shared memory entry suitable for use in shared memory linked list
  *   returned in pass-by-reference `shmep` pointer. This function always
  *   allocates a shared memory entry, regardless of flags. The rest of this
@@ -1040,12 +1115,9 @@ uintptr_t optee_va_to_pa(FAR const void *va)
  *     be allocated. In this case `addr` will be ignored. The allocated
  *     buffer will be aligned to `priv->alignment`. `TEE_SHM_ALLOC` flag
  *     is reserved for kernel use only.
- *   - If `TEE_SHM_SEC_REGISTER` is specified, then the memory specified by
+ *   - If `TEE_SHM_REGISTER` is specified, then the memory specified by
  *     `addr` or allocated through `TEE_SHM_ALLOC`, will be registered with
  *     OP-TEE as dynamic shared memory.
- *   - If `TEE_SHM_REGISTER` is specified, then the memory specified by
- *     `addr` or allocated through `TEE_SHM_ALLOC`, will be added to the
- *     driver's private data structure linked list of shared memory chunks.
  *
  *   Use `optee_shm_free()` to undo this operation, i.e. to free,
  *   unregister, and/or remove from the list the entry returned in `shmep`
@@ -1071,14 +1143,13 @@ int optee_shm_alloc(FAR struct optee_priv_data *priv, 
FAR void *addr,
                     FAR struct optee_shm_entry **shmep)
 {
   FAR struct optee_shm_entry *shme;
-  irqstate_t irqstate;
   FAR void *ptr;
-  int ret;
+  int ret = -ENOMEM;
 
   shme = kmm_zalloc(sizeof(struct optee_shm_entry));
   if (shme == NULL)
     {
-      return -ENOMEM;
+      return ret;
     }
 
   if (flags & TEE_SHM_ALLOC)
@@ -1099,36 +1170,34 @@ int optee_shm_alloc(FAR struct optee_priv_data *priv, 
FAR void *addr,
 
   if (ptr == NULL)
     {
-      ret = -ENOMEM;
       goto err;
     }
 
-  shme->shm.addr = (uintptr_t)ptr;
-  shme->shm.length = size;
-  shme->shm.flags = flags;
+  shme->priv = priv;
+  shme->addr = (uintptr_t)ptr;
+  shme->length = size;
+  shme->flags = flags;
+  shme->id = idr_alloc(priv->shms, shme, 0, 0);
 
-  if (flags & TEE_SHM_SEC_REGISTER)
+  if (shme->id < 0)
     {
-      ret = optee_shm_sec_register(priv, shme);
-      if (ret < 0)
-        {
-          goto err;
-        }
+      goto err;
     }
 
   if (flags & TEE_SHM_REGISTER)
     {
-      irqstate = spin_lock_irqsave(&priv->lock);
-
-      shme->shm.id = optee_shm_next_id(priv);
-      list_add_head(&priv->shm_list, &shme->node);
-
-      spin_unlock_irqrestore(&priv->lock, irqstate);
+      ret = optee_shm_register(priv, shme);
+      if (ret < 0)
+        {
+          goto err_with_idr;
+        }
     }
 
   *shmep = shme;
   return 0;
 
+err_with_idr:
+  idr_remove(priv->shms, shme->id);
 err:
   kmm_free(shme);
   if (flags & TEE_SHM_ALLOC)
@@ -1146,7 +1215,6 @@ err:
  *   Free and/or unregister shared memory allocated by `optee_shm_alloc()`.
  *
  * Parameters:
- *   priv  - The driver's private data structure
  *   shme  - Pointer to shared memory entry to free. Can be NULL, in which
  *           case, this is a no-op.
  *
@@ -1155,38 +1223,31 @@ err:
  *
  ****************************************************************************/
 
-void optee_shm_free(FAR struct optee_priv_data *priv,
-                    FAR struct optee_shm_entry *shme)
+void optee_shm_free(FAR struct optee_shm_entry *shme)
 {
-  irqstate_t irqstate;
-
   if (!shme)
     {
       return;
     }
 
-  if (shme->shm.flags & TEE_SHM_SEC_REGISTER)
+  if (shme->flags & TEE_SHM_REGISTER)
     {
-      optee_shm_sec_unregister(priv, shme);
+      optee_shm_unregister(shme->priv, shme);
     }
 
-  if (shme->shm.flags & TEE_SHM_REGISTER)
+  if (shme->flags & TEE_SHM_ALLOC)
     {
-      irqstate = spin_lock_irqsave(&priv->lock);
-
-      if (list_in_list(&shme->node))
-        {
-          list_delete(&shme->node);
-        }
-
-      spin_unlock_irqrestore(&priv->lock, irqstate);
+      kmm_free((FAR void *)(uintptr_t)shme->addr);
     }
 
-  if (shme->shm.flags & TEE_SHM_ALLOC)
+  if (!(shme->flags & (TEE_SHM_ALLOC | TEE_SHM_REGISTER)))
     {
-      kmm_free((FAR void *)(uintptr_t)shme->shm.addr);
+      /* allocated by optee_ioctl_shm_alloc(), need to unmap */
+
+      munmap((FAR void *)(uintptr_t)shme->addr, shme->length);
     }
 
+  idr_remove(shme->priv->shms, shme->id);
   kmm_free(shme);
 }
 
diff --git a/drivers/misc/optee.h b/drivers/misc/optee.h
index 191af10232..59e2c1512e 100644
--- a/drivers/misc/optee.h
+++ b/drivers/misc/optee.h
@@ -30,8 +30,7 @@
 #include <nuttx/config.h>
 #include <nuttx/compiler.h>
 #include <nuttx/tee.h>
-#include <nuttx/list.h>
-#include <nuttx/spinlock.h>
+#include <nuttx/idr.h>
 
 #include "optee_msg.h"
 
@@ -46,17 +45,19 @@
  * Public Types
  ****************************************************************************/
 
-struct optee_shm_entry
+struct optee_priv_data
 {
-  struct list_node node;
-  struct tee_ioctl_shm_register_data shm;
+  uintptr_t alignment;        /* Transport-specified message alignment */
+  FAR struct idr_s *shms;     /* An RB tree of all shm entries */
 };
 
-struct optee_priv_data
+struct optee_shm_entry
 {
-  uintptr_t alignment;        /* Transport-specified message alignment */
-  struct list_node shm_list;  /* A list of all shm registered */
-  spinlock_t lock;            /* Lock used to guard list accesses */
+  FAR struct optee_priv_data *priv;
+  int32_t id;
+  uint64_t addr;
+  uint64_t length;
+  uint32_t flags;
 };
 
 /****************************************************************************
@@ -80,8 +81,7 @@ uintptr_t optee_va_to_pa(FAR const void *va);
 int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr,
                     size_t size, uint32_t flags,
                     FAR struct optee_shm_entry **shmep);
-void optee_shm_free(FAR struct optee_priv_data *priv,
-                    FAR struct optee_shm_entry *shme);
+void optee_shm_free(FAR struct optee_shm_entry *shme);
 int optee_transport_init(void);
 int optee_transport_open(FAR struct optee_priv_data **priv);
 void optee_transport_close(FAR struct optee_priv_data *priv);
diff --git a/drivers/misc/optee_smc.c b/drivers/misc/optee_smc.c
index b4886a644a..3077a3b712 100644
--- a/drivers/misc/optee_smc.c
+++ b/drivers/misc/optee_smc.c
@@ -187,10 +187,9 @@ static void optee_smc_handle_rpc(FAR struct 
optee_priv_data *priv_,
   switch (rpc_func)
     {
       case OPTEE_SMC_RPC_FUNC_ALLOC:
-        if (!optee_shm_alloc(priv_, NULL, par->a1,
-                             TEE_SHM_ALLOC | TEE_SHM_REGISTER, &shme))
+        if (!optee_shm_alloc(priv_, NULL, par->a1, TEE_SHM_ALLOC, &shme))
           {
-            shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->shm.addr);
+            shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->addr);
             reg_pair_from_64(shme_pa, &par->a1, &par->a2);
             reg_pair_from_64((uintptr_t)shme, &par->a4, &par->a5);
           }
@@ -204,7 +203,7 @@ static void optee_smc_handle_rpc(FAR struct optee_priv_data 
*priv_,
       case OPTEE_SMC_RPC_FUNC_FREE:
         shme = (FAR struct optee_shm_entry *)
                   reg_pair_to_uintptr(par->a1, par->a2);
-        optee_shm_free(priv_, shme);
+        optee_shm_free(shme);
         break;
 
       case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
diff --git a/include/nuttx/tee.h b/include/nuttx/tee.h
index ed50eac0cb..860021e3fb 100644
--- a/include/nuttx/tee.h
+++ b/include/nuttx/tee.h
@@ -378,12 +378,10 @@ struct tee_iocl_supp_send_arg
 
 #define TEE_IOC_SUPPL_SEND _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 7)
 
-/* Shared memory specific defines */
+/* Shared memory-specific defines */
 
-#define TEE_SHM_REGISTER     (1 << 0) /* In list of shared memory */
-#define TEE_SHM_SEC_REGISTER (1 << 1) /* TEE notified of this memory */
-#define TEE_SHM_ALLOC        (1 << 2) /* The memory is malloced() and must
-                                       * be freed() */
+#define TEE_SHM_ALLOC    (1 << 0) /* Kernel-malloced and must freed */
+#define TEE_SHM_REGISTER (1 << 1) /* Registered with TEE OS */
 
 /* struct tee_ioctl_shm_register_data - Shared memory register argument
  * addr:      [in] Start address of shared memory to register

Reply via email to