xiaoxiang781216 commented on code in PR #16309:
URL: https://github.com/apache/nuttx/pull/16309#discussion_r2072846960


##########
drivers/misc/Kconfig:
##########
@@ -43,31 +43,66 @@ choice
        prompt "Select OP-TEE dev implementation"
        default DEV_OPTEE_NONE
        ---help---
-               There are two implementations of optee server,
+               There are three implementations of optee server,
                one is soft tee server which does not distinguish
                between secure and non-secure states and uses socket 
communication,
-               and the other is teeos which runs in the secure state of
-               the cpu and uses rpmsg cross-core communication.
+               and the other two is teeos which runs in the secure state of
+               the cpu and uses either rpmsg cross-core communication or ARM64 
SMCs.
 
 config DEV_OPTEE_LOCAL
        bool "OPTEE Local Socket Support"
        depends on NET_LOCAL
+       depends on LIBC_MEMFD_SHMFS
        depends on ALLOW_BSD_COMPONENTS
 
 config DEV_OPTEE_RPMSG
        bool "OP-TEE RPMSG Socket Support"
        depends on NET_RPMSG
+       depends on LIBC_MEMFD_SHMFS
+       depends on ALLOW_BSD_COMPONENTS
+
+config DEV_OPTEE_SMC64

Review Comment:
   since SMC also support for arm32, could we remove 64 or add both 32 and 64?



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;
+    }
+
+  if (up_addrenv_user_vaddr((uintptr_t)va) &&
+      up_addrenv_user_vaddr((uintptr_t)va + size - 1))
+    {
+      return 1;
+    }
+
+  return 0;

Review Comment:
   ```suggestion
     return false;
   ```



##########
drivers/misc/optee.c:
##########
@@ -653,5 +1849,47 @@ static int optee_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
 
 int optee_register(void)
 {
+#ifdef CONFIG_DEV_OPTEE_SMC64

Review Comment:
   could we move the test to apps folder?



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,

Review Comment:
   add optee_ prefix



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;

Review Comment:
   ```suggestion
         return true;
   ```



##########
drivers/misc/optee_smc.h:
##########
@@ -0,0 +1,449 @@
+/****************************************************************************
+ * drivers/misc/optee_smc.h
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ * Copyright (c) 2015-2018, Linaro Limited
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_MISC_OPTEE_SMC_H
+#define __DRIVERS_MISC_OPTEE_SMC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+#include <arch/syscall.h>
+/* #include <syscall.h> */

Review Comment:
   remove



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))

Review Comment:
   use the macro from nuttx.h



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;
+    }
+
+  if (up_addrenv_user_vaddr((uintptr_t)va) &&
+      up_addrenv_user_vaddr((uintptr_t)va + size - 1))
+    {
+      return 1;

Review Comment:
   ```suggestion
         return true;
   ```



##########
Documentation/guides/optee.rst:
##########
@@ -0,0 +1,307 @@
+=======================
+Interfacing with OP-TEE
+=======================
+
+Overview
+========
+
+NuttX supports basic interfacing with OP-TEE OS through three different
+transports: local network, RPMsg, and native Secure Monitor Calls (SMCs)
+on arm64. Tasks can interface with the OP-TEE driver (and in turn with the
+OP-TEE OS) via IOCTLs on the TEE (``/dev/tee#``) character device. This
+interface should allow use-of/integration-with libteec, although this is
+not officially supported by NuttX, and is out of the scope of this guide.
+
+The driver supports opening and closing sessions, allocating and registering
+shared memory, and invoking functions on OP-TEE Trusted Applications (TAs).
+It does not (yet) support reverse direction commands (TA -> Normal World)
+to something like a TEE supplicant.
+
+Enabling the OP-TEE Driver
+==========================
+
+The driver is enabled using one of:
+
+- ``CONFIG_DEV_OPTEE_LOCAL``
+- ``CONFIG_DEV_OPTEE_RPMSG``
+- ``CONFIG_DEV_OPTEE_SMC64``
+
+All of the above require also ``CONFIG_ALLOW_BSD_COMPONENTS`` and
+``CONFIG_LIBC_MEMFD_SHMFS``, which in turn requires ``CONFIG_FS_SHMFS``. So,
+at a bare minimum, to enable the driver one would need something like the
+following:
+
+.. code-block::
+
+  CONFIG_ALLOW_BSD_COMPONENTS=y
+  CONFIG_DEV_OPTEE_SMC64=y
+  CONFIG_FS_SHMFS=y
+  CONFIG_LIBC_MEMFD_SHMFS=y
+
+Each implementation (local, RPMsg, or SMC64) may have further dependencies
+(e.g. RPMsg requires ``CONFIG_NET_RPMSG`` etc, SMC64 requires
+``CONFIG_ARCH_ARM64``) and may have further parameters to configure (e.g.
+RPMsg remote CPU name through ``CONFIG_OPTEE_REMOTE_CPU_NAME``).
+``CONFIG_DEV_OPTEE_SMC64`` in particular, allows the use of
+``CONFIG_DEV_OPTEE_SMC64_TEST`` which will run some test code just before 
driver
+registration with some syslog messages during boot.
+
+In any case, successful registration of the driver can be verified by looking
+into ``/dev/tee0``. For instance, incompatibility with the TEE OS running
+in the system, will prevent the ``/dev/tee0`` character device from being
+registered.
+
+IOCTLs supported
+================
+
+All IOCTLs return negative error codes on failure. All of them return 0
+on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``).
+
+- ``TEE_IOC_VERSION`` : Query the version and capabilities of the TEE driver.
+
+  - Use the ``struct tee_ioctl_version_data`` to get the version and
+    capabilities. This driver supports OP-TEE so you should expect to
+    receive only ``TEE_IMPL_ID_OPTEE`` in ``.impl_id`` and ``TEE_OPTEE_CAP_TZ``
+    in ``.impl_caps``. The driver is GlobalPlatform compliant, and you should
+    always expect to receive ``TEE_GEN_CAP_GP | TEE_GEN_CAP_MEMREF_NULL`` in
+    ``.gen_caps``. If using the SMC64 implementation, the driver supports also
+    shared memory registration, so you can expect also ``TEE_GEN_CAP_REG_MEM``
+    in ``.gen_caps``.
+
+- ``TEE_IOC_OPEN_SESSION`` :  Open a session with a Trusted Application.
+
+  - Expects a ``struct tee_ioctl_buf_data`` pointer, pointing to a
+    ``struct tee_ioctl_open_session_arg`` instance with at minimum, the 
``.uuid``
+    set. You can typically use ``uuid_enc_be()`` to encode a ``uuid_t`` struct
+    to the raw byte buffer expected in the ``.uuid`` field. After a successful
+    call, you can expect to get a session identifier back in the ``.session``
+    field.
+
+- ``TEE_IOC_CLOSE_SESSION`` : Close a session with a Trusted Application.
+
+  - Expects a pointer to a ``struct tee_ioctl_close_session_arg`` with the
+    ``.session`` field set to the identifier of the session to close.
+
+- ``TEE_IOC_INVOKE`` : Invoke a function on a previously opened session to a 
Trusted Application.
+
+  - Expects a ``struct tee_ioctl_buf_data`` pointer, pointing to a
+    ``struct tee_ioctl_invoke_arg`` instance. You can use the
+    ``TEE_IOCTL_PARAM_SIZE()`` macro to calculate the size of the
+    variable-length array of ``struct tee_ioctl_param`` parameters in the
+    invoke arguments struct. At minimum, the interface expects the fields
+    ``.func``, ``.session``, ``.num_params``, and ``.params`` to be set.
+    ``.cancel_id`` can be optionally set to enable later canceling of this
+    command if needed.
+    You might notice that ``struct tee_ioctl_param`` has rather obscure field
+    names (``.a``, ``.b``, ``.c``). This can be improved with a union in the
+    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``).
+
+- ``TEE_IOC_CANCEL`` : Cancel a currently invoked command.
+
+  - Expects a ``struct tee_ioctl_cancel_arg`` pointer with the ``.session``
+    and ``.cancel_id`` fields set.
+
+- ``TEE_IOC_SHM_ALLOC`` : Allocate shared memory between the user space and 
the secure OS.
+
+  - 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 a suggested identifier for the allocation
+    in ``.id``.
+
+- ``TEE_IOC_SHM_REGISTER`` : Register a shared memory reference with the 
secure OS.
+
+  - Currently only available with ``CONFIG_DEV_OPTEE_SMC64``.
+    Expects a pointer to a ``struct tee_ioctl_shm_register_data`` instance with
+    all fields set. ``.id`` is only used with the driver for uniqueness
+    checking and is not related to the shared memory identifier. ``.flags``
+    can be any combination of ``TEE_SHM_REGISTER`` and ``TEE_SHM_SEC_REGISTER``
+    but not ``TEE_SHM_ALLOC``.
+    ``TEE_SHM_REGISTER`` registers the memory with the driver for automatic
+    cleanup (not freeing!) during ``/dev/tee#`` character device close.
+    ``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``).
+
+Typical usage
+=============
+
+#. Include the necessary headers:
+
+   .. code-block:: c
+
+     #include <stdio.h>
+     #include <stdlib.h>
+     #include <fcntl.h>
+     #include <unistd.h>
+     #include <errno.h>
+     #include <sys/ioctl.h>
+     #include <nuttx/tee.h>
+     #include <uuid.h>
+
+#. Open the TEE character device
+
+   .. code-block:: c
+
+     int fd = open("/dev/tee0", O_RDONLY | O_NONBLOCK);
+
+#. Check the version and capabilities
+
+   .. code-block:: c
+
+     struct tee_ioctl_version_data ioc_ver;
+
+     int 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;
+       }
+
+     [...check ioc_ver accordingly...]
+
+#. Open a session with a Trusted Application
+
+   .. code-block:: c
+
+     const uuid_t *uuid = [...];
+     struct tee_ioctl_open_session_arg ioc_opn = { 0 };
+     struct tee_ioctl_buf_data ioc_buf;
+
+     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;
+       }
+
+     [...use ioc_opn.session returned...]
+
+#. Invoke a function of the Trusted Application
+
+   .. code-block:: c
+
+     const size_t num_params = 1;
+     struct tee_ioctl_invoke_arg *ioc_args;
+     struct tee_ioctl_buf_data ioc_buf;
+     size_t ioc_args_len;
+
+     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 = <SOME_FUNCTION_ID>;
+     ioc_args->session = ioc_opn.session;
+     ioc_args->num_params = num_params;
+     ioc_args->params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+
+     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;
+       }
+
+     [...use result (if any) in ioc_args->params...]
+
+#. Allocate shared memory through the driver
+
+   .. code-block:: c
+
+     struct tee_ioctl_shm_alloc_data ioc_alloc = { 0 };
+     int memfd;
+     void *shm;
+
+     ioc_alloc.size = 1024;
+
+     memfd = ioctl(fd, TEE_IOC_SHM_ALLOC, (unsigned long)&ioc_alloc);
+     if (memfd < 0)
+       {
+         return memfd;
+       }
+
+     shm = mmap(NULL, ioc_alloc.size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                memfd, 0);
+     if (shm == MAP_FAILED)
+       {
+         close(memfd);
+         return -ENOMEM;
+       }
+
+#. Register shared memory with the driver and the secure OS
+
+   .. 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 */
+
+     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.id = (int32_t)(uintptr_t)shm;;

Review Comment:
   ```suggestion
        ioc_reg.id = (int32_t)(uintptr_t)shm;
   ```



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;
+    }
+
+  if (up_addrenv_user_vaddr((uintptr_t)va) &&
+      up_addrenv_user_vaddr((uintptr_t)va + size - 1))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+#else /* !CONFIG_ARCH_ADDRENV */
+#define virt_to_phys(va)                ((uintptr_t)va)
+#define safe_va_range(addr, size)       (true)
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+static int is_optee_api(optee_invoke_fn *invoke_fn)
+{
+  struct arm64_smccc_res res;
+
+  invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+  return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+         res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
+}
+
+static void print_os_revision(optee_invoke_fn *invoke_fn)
+{
+  union os_revision res =
+  {
+    .result =
+    {
+      .build_id = 0
+    }
+  };
+
+  invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.build_id)
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu (%08lx)\n",
+            res.result.major, res.result.minor,
+            res.result.build_id);
+    }
+  else
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu\n",
+            res.result.major, res.result.minor);
+    }
+}
+
+static int api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_calls_revision_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+  return res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+         (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR;
+}
+
+static int exchange_capabilities(optee_invoke_fn *invoke_fn,
+                                 unsigned long *sec_caps)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_exchange_capabilities_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES,
+            OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.status != OPTEE_SMC_RETURN_OK)
+    {
+      return 0;
+    }
+
+  *sec_caps = res.result.capabilities;
+
+  return 1;
+}
+
+/****************************************************************************
+ * Name: reg_pair_to_ptr
+ *
+ * Description:
+ *   Make a pointer of 2 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of the pointer
+ *   reg1   - Low bits of the pointer
+ *
+ * Returned Values:
+ *    The combined result. Note that if a pointer is 32-bit wide `reg0`
+ *    will be discarded.
+ *
+ ****************************************************************************/
+
+static void *reg_pair_to_ptr(uint32_t reg0, uint32_t reg1)

Review Comment:
   add FAR for ALL pointers



##########
drivers/misc/optee.c:
##########
@@ -611,30 +1659,178 @@ optee_ioctl_shm_alloc(FAR struct 
tee_ioctl_shm_alloc_data *data)
 
 static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 {
-  FAR struct socket *psock = filep->f_priv;
+  FAR struct optee_priv_data *priv = filep->f_priv;
   FAR void *parg = (FAR void *)arg;
 
   switch (cmd)
     {
       case TEE_IOC_VERSION:
         return optee_ioctl_version(parg);
       case TEE_IOC_OPEN_SESSION:
-        return optee_ioctl_open_session(psock, parg);
+        return optee_ioctl_open_session(priv, parg);
       case TEE_IOC_INVOKE:
-        return optee_ioctl_invoke(psock, parg);
+        return optee_ioctl_invoke(priv, parg);
       case TEE_IOC_CLOSE_SESSION:
-        return optee_ioctl_close_session(psock, parg);
+        return optee_ioctl_close_session(priv, parg);
       case TEE_IOC_CANCEL:
-        return optee_ioctl_cancel(psock, parg);
+        return optee_ioctl_cancel(priv, parg);
       case TEE_IOC_SHM_ALLOC:
         return optee_ioctl_shm_alloc(parg);
+#ifdef CONFIG_DEV_OPTEE_SMC64
+      case TEE_IOC_SHM_REGISTER:
+        return optee_ioctl_shm_register(priv, parg);
+#endif
       default:
         return -ENOTTY;
     }
 
   return 0;
 }
 
+/****************************************************************************
+ * Name: optee_shm_alloc
+ *
+ * Description:
+ *   Allocate, register and add shared memory for use with OP-TEE calls.
+ *   This wrapper will call `optee_shm_add()` setting alignment to 0, and
+ *   enforcing flags `TEE_SHM_SEC_REGISTER`, `TEE_SHM_REGISTER`, and
+ *   `TEE_SHM_ALLOC`.
+ *
+ *   Use `optee_shm_free()` to undo this operation, i.e. to free,
+ *   unregister, and/or remove from the list the entry returned in `shmep`
+ *   and the contained buffer.
+ *
+ * Parameters:
+ *   priv  - the driver's private data structure
+ *   size  - the size of the shared memory buffer to allocate.
+ *   flags - flags specifying the behaviour of this function. Supports
+ *           combinations of `TEE_SHM_{ALLOC,REGISTER,SEC_REGISTER}`.
+ *   shmep - Pass-by-reference pointer to return the shared memory entry
+ *           allocated. Cannot be NULL.
+ *
+ * Returned Values:
+ *   0 on success, negative error code otherwise.
+ *
+ ****************************************************************************/
+
+ #ifdef CONFIG_DEV_OPTEE_SMC64_TEST

Review Comment:
   ```suggestion
   #ifdef CONFIG_DEV_OPTEE_SMC64_TEST
   ```



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)

Review Comment:
   let's add optee_ prefix to ALL functions



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;
+    }
+
+  if (up_addrenv_user_vaddr((uintptr_t)va) &&
+      up_addrenv_user_vaddr((uintptr_t)va + size - 1))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+#else /* !CONFIG_ARCH_ADDRENV */
+#define virt_to_phys(va)                ((uintptr_t)va)
+#define safe_va_range(addr, size)       (true)
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+static int is_optee_api(optee_invoke_fn *invoke_fn)
+{
+  struct arm64_smccc_res res;
+
+  invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+  return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+         res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
+}
+
+static void print_os_revision(optee_invoke_fn *invoke_fn)
+{
+  union os_revision res =
+  {
+    .result =
+    {
+      .build_id = 0
+    }
+  };
+
+  invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.build_id)
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu (%08lx)\n",
+            res.result.major, res.result.minor,
+            res.result.build_id);
+    }
+  else
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu\n",
+            res.result.major, res.result.minor);
+    }
+}
+
+static int api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_calls_revision_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+  return res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+         (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR;
+}
+
+static int exchange_capabilities(optee_invoke_fn *invoke_fn,
+                                 unsigned long *sec_caps)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_exchange_capabilities_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES,
+            OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.status != OPTEE_SMC_RETURN_OK)
+    {
+      return 0;
+    }
+
+  *sec_caps = res.result.capabilities;
+
+  return 1;
+}
+
+/****************************************************************************
+ * Name: reg_pair_to_ptr
+ *
+ * Description:
+ *   Make a pointer of 2 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of the pointer
+ *   reg1   - Low bits of the pointer
+ *
+ * Returned Values:
+ *    The combined result. Note that if a pointer is 32-bit wide `reg0`
+ *    will be discarded.
+ *
+ ****************************************************************************/
+
+static void *reg_pair_to_ptr(uint32_t reg0, uint32_t reg1)
+{
+  return (void *)(uintptr_t)(((uint64_t)reg0 << 32) | reg1);
+}
+
+/****************************************************************************
+ * Name: reg_pair_from_64
+ *
+ * Description:
+ *   Split a 64-bit value into two 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of `val`
+ *   reg1   - Low bits of `val`
+ *   val    - The value to split
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void reg_pair_from_64(uint32_t *reg0, uint32_t *reg1, uint64_t val)
+{
+  *reg0 = val >> 32;
+  *reg1 = val;
+}
+
+/****************************************************************************
+ * Name: dcache_enabled
+ *
+ * Description:
+ *   Return arm64 EL1 D-Cache status. This should probably be re-located in
+ *   arm64_cache.c once respective implementations for other archs are
+ *   provided.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Values:
+ *   0 if CONFIG_ARM64_DCACHE_DISABLE is set, or EL1 D-Cache is not enabled.
+ *   Non-zero otherwise.
+ *
+ ****************************************************************************/
+
+static int dcache_enabled(void)
+{
+#ifdef CONFIG_ARM64_DCACHE_DISABLE
+  return 0;
+#else
+
+  /* arm64_cache.c assumes EL1 all around, so do we.
+   * NuttX doesn't support EL2 yet
+   */
+
+  uint64_t value = read_sysreg(sctlr_el1);

Review Comment:
   please add api to cache.h or assume the cache is always enabled



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;
+    }
+
+  if (up_addrenv_user_vaddr((uintptr_t)va) &&
+      up_addrenv_user_vaddr((uintptr_t)va + size - 1))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+#else /* !CONFIG_ARCH_ADDRENV */
+#define virt_to_phys(va)                ((uintptr_t)va)
+#define safe_va_range(addr, size)       (true)
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+static int is_optee_api(optee_invoke_fn *invoke_fn)
+{
+  struct arm64_smccc_res res;
+
+  invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+  return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+         res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
+}
+
+static void print_os_revision(optee_invoke_fn *invoke_fn)
+{
+  union os_revision res =
+  {
+    .result =
+    {
+      .build_id = 0
+    }
+  };
+
+  invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.build_id)
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu (%08lx)\n",
+            res.result.major, res.result.minor,
+            res.result.build_id);
+    }
+  else
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu\n",
+            res.result.major, res.result.minor);
+    }
+}
+
+static int api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_calls_revision_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+  return res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+         (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR;
+}
+
+static int exchange_capabilities(optee_invoke_fn *invoke_fn,
+                                 unsigned long *sec_caps)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_exchange_capabilities_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES,
+            OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.status != OPTEE_SMC_RETURN_OK)
+    {
+      return 0;
+    }
+
+  *sec_caps = res.result.capabilities;
+
+  return 1;
+}
+
+/****************************************************************************
+ * Name: reg_pair_to_ptr
+ *
+ * Description:
+ *   Make a pointer of 2 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of the pointer
+ *   reg1   - Low bits of the pointer
+ *
+ * Returned Values:
+ *    The combined result. Note that if a pointer is 32-bit wide `reg0`
+ *    will be discarded.
+ *
+ ****************************************************************************/
+
+static void *reg_pair_to_ptr(uint32_t reg0, uint32_t reg1)
+{
+  return (void *)(uintptr_t)(((uint64_t)reg0 << 32) | reg1);
+}
+
+/****************************************************************************
+ * Name: reg_pair_from_64
+ *
+ * Description:
+ *   Split a 64-bit value into two 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of `val`
+ *   reg1   - Low bits of `val`
+ *   val    - The value to split
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void reg_pair_from_64(uint32_t *reg0, uint32_t *reg1, uint64_t val)
+{
+  *reg0 = val >> 32;
+  *reg1 = val;
+}
+
+/****************************************************************************
+ * Name: dcache_enabled
+ *
+ * Description:
+ *   Return arm64 EL1 D-Cache status. This should probably be re-located in
+ *   arm64_cache.c once respective implementations for other archs are
+ *   provided.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Values:
+ *   0 if CONFIG_ARM64_DCACHE_DISABLE is set, or EL1 D-Cache is not enabled.
+ *   Non-zero otherwise.
+ *
+ ****************************************************************************/
+
+static int dcache_enabled(void)
+{
+#ifdef CONFIG_ARM64_DCACHE_DISABLE
+  return 0;
+#else
+
+  /* arm64_cache.c assumes EL1 all around, so do we.
+   * NuttX doesn't support EL2 yet
+   */
+
+  uint64_t value = read_sysreg(sctlr_el1);
+  return (value & SCTLR_C_BIT) != 0;
+#endif
+}
+
+/****************************************************************************
+ * Name: flush_shm_dcache
+ *
+ * Description:
+ *   Clean and invalidate shared memory D cache on OP-TEE message arguments
+ *   and OP-TEE shared memory allocations registered in the driver's private
+ *   data linked list.
+ *
+ * Parameters:
+ *   priv  - the driver's private data structure
+ *   arg   - the OP-TEE message arguments to flush
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void flush_shm_dcache(FAR struct optee_priv_data *priv,
+                             FAR struct optee_msg_arg *arg)
+{
+  struct optee_shm_entry *shme;
+  size_t sz = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
+
+  up_flush_dcache((uintptr_t)arg, (uintptr_t)arg + sz);
+
+  SLIST_FOREACH(shme, &priv->list_shm, link)
+    {
+      up_flush_dcache((uintptr_t)shme->shm.addr,
+                      (uintptr_t)shme->shm.addr + shme->shm.length);
+    }
+}
+
+static void handle_rpc(FAR struct optee_priv_data *priv,
+                       FAR struct rpc_param *param)
+{
+  FAR struct optee_shm_entry *shme;
+
+  switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0))
+    {
+      case OPTEE_SMC_RPC_FUNC_ALLOC:
+        if (!optee_shm_add(priv, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
+              param->a1, TEE_SHM_ALLOC | TEE_SHM_REGISTER,
+              &shme))
+          {
+            reg_pair_from_64(&param->a1, &param->a2,
+                virt_to_phys((void *)(uintptr_t)shme->shm.addr));
+
+            /* "cookie" */
+
+            reg_pair_from_64(&param->a4, &param->a5, (uintptr_t)shme);
+          }
+        else
+          {
+            param->a1 = 0;
+            param->a2 = 0;
+            param->a4 = 0;
+            param->a5 = 0;
+          }
+        break;
+      case OPTEE_SMC_RPC_FUNC_FREE:
+        shme = reg_pair_to_ptr(param->a1, param->a2);
+        optee_shm_free(shme);
+        break;
+      case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
+        break;
+      case OPTEE_SMC_RPC_FUNC_CMD:
+        shme = reg_pair_to_ptr(param->a1, param->a2);
+
+        /* optee_suppl_cmd(priv, shme, page_list); */
+
+        syslog(LOG_ERR, "OP-TEE RPC handling of supplicant commands not "
+                        "implemented");
+        break;
+      default:
+        break;
+    }
+
+  param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+}
+
+static int call_err_to_res(uint32_t call_err)
+{
+  switch (call_err)
+    {
+      case OPTEE_SMC_RETURN_OK:
+        return TEE_SUCCESS;
+      default:
+        return (int)call_err;
+    }
+}
+
+static int optee_smc64_call(FAR struct optee_priv_data *priv,
+                            FAR struct optee_msg_arg *arg)
+{
+  struct arm64_smccc_res res;
+  struct rpc_param param =
+  {
+    .a0 = OPTEE_SMC_CALL_WITH_ARG
+  };
+
+  reg_pair_from_64(&param.a1, &param.a2, virt_to_phys(arg));
+
+  while (1)
+    {
+      memset(&res, 0, sizeof(struct arm64_smccc_res));
+
+      /* If cache is off from NuttX, sync the cache shared with OP-TEE */
+
+      if (!dcache_enabled())

Review Comment:
   if dcache isn't enabled, why do we need flush the dcache?



##########
drivers/misc/optee.c:
##########
@@ -36,165 +36,977 @@
 #include <sys/mman.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <sys/queue.h>
+
+#ifdef CONFIG_ARCH_ADDRENV
+#  include <nuttx/pgalloc.h>
+#  include <nuttx/sched.h>
+#  include <nuttx/arch.h>
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+#  include <syslog.h>
+#  include <uuid.h>
+#  include <nuttx/bits.h>
+#  include <nuttx/cache.h>
+#  include <arch/syscall.h>
+#  include "optee_smc.h"
+#endif
 
 #include "optee_msg.h"
 
-/****************************************************************************
- *   The driver's main purpose is to support the porting of the open source
- * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
- *   The basic function of the driver module is to convert
- * the REE application layer data and send it to the TEE through rpmsg.
- * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
- ****************************************************************************/
+/****************************************************************************
+ *   The driver's main purpose is to support the porting of the open source
+ * component optee_client (https://github.com/OP-TEE/optee_client) to NuttX.
+ *   The basic function of the driver module is to convert
+ * the REE application layer data and send it to the TEE through rpmsg.
+ * TEE implementation is optee_os(https://github.com/OP-TEE/optee_os).
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some GlobalPlatform error codes used in this driver */
+
+#define TEE_SUCCESS                    0x00000000
+#define TEE_ERROR_BAD_PARAMETERS       0xFFFF0006
+#define TEE_ERROR_NOT_SUPPORTED        0xFFFF000A
+#define TEE_ERROR_COMMUNICATION        0xFFFF000E
+#define TEE_ERROR_OUT_OF_MEMORY        0xFFFF000C
+#define TEE_ERROR_BUSY                 0xFFFF000D
+#define TEE_ERROR_SHORT_BUFFER         0xFFFF0010
+
+#define TEE_ORIGIN_COMMS               0x00000002
+
+#define OPTEE_MAX_IOVEC_NUM            7
+#define OPTEE_MAX_PARAM_NUM            6
+
+#define __round_mask(x, y)             ((__typeof__(x))((y)-1))
+#define round_up(x, y)                 ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y)               ((x) & ~__round_mask(x, y))
+#define DIV_ROUND_UP(n,d)              (((n) + (d) - 1) / (d))
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t)) - 1)
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+
+/* is there a nice way to include arm64_arch.h instead? */
+#  define SCTLR_C_BIT                  BIT(2)
+
+#  ifdef CONFIG_DEV_OPTEE_SMC64_TEST
+#    define PTA_DEVICE_ENUM            { 0x7011a688, 0xddde, 0x4053, \
+                                         0xa5, 0xa9, \
+                                         { 0x7b, 0x3c, 0x4d, 0xdf, \
+                                           0x13, 0xb8 } }
+#    define PTA_CMD_GET_DEVICES        0x0
+#  endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm64_smccc_res *);
+
+struct rpc_param
+{
+  uint32_t a0;
+  uint32_t a1;
+  uint32_t a2;
+  uint32_t a3;
+  uint32_t a4;
+  uint32_t a5;
+  uint32_t a6;
+  uint32_t a7;
+};
+
+union os_revision
+{
+  struct arm64_smccc_res smccc;
+  struct optee_smc_call_get_os_revision_result result;
+};
+#endif
+
+struct optee_priv_data;
+
+struct optee_shm_entry
+{
+  struct optee_priv_data *priv;
+  struct tee_ioctl_shm_register_data shm;
+  SLIST_ENTRY(optee_shm_entry) link;
+};
+
+SLIST_HEAD(optee_shm_head, optee_shm_entry);
+
+struct optee_priv_data
+{
+#ifdef CONFIG_DEV_OPTEE_SMC64
+  optee_invoke_fn *invoke_fn;
+#else
+  FAR struct socket *psock;
+#endif
+  struct optee_shm_head list_shm;
+};
+
+struct page_data
+{
+  uint64_t pages_list[PAGELIST_ENTRIES_PER_PAGE];
+  uint64_t next_page_data;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* The file operation functions */
+
+static int optee_open(FAR struct file *filep);
+static int optee_close(FAR struct file *filep);
+static int optee_ioctl(FAR struct file *filep, int cmd,
+                       unsigned long arg);
+
+/* Other forward-declared functions */
+
+static int optee_shm_add(FAR struct optee_priv_data *priv, uintptr_t align,
+                         FAR void *addr, size_t size, uint32_t flags,
+                         FAR struct optee_shm_entry **shmep);
+static void optee_shm_free(FAR struct optee_shm_entry *shme);
+static int get_msg_arg(FAR struct optee_priv_data *priv,
+                       uint32_t num_params,
+                       FAR struct optee_shm_entry **shmep,
+                       FAR struct optee_msg_arg **msg_arg);
+static int
+optee_do_call_with_arg(FAR struct optee_priv_data *priv,
+                       FAR struct optee_msg_arg *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* File operations */
+
+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 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: virt_to_phys
+ *
+ * Description:
+ *   Convert the specified virtual address to a physical address. If the
+ *   virtual address does not belong to the user, it is assumed to be a
+ *   kernel virtual address with a 1-1 mapping and the VA is returned as-is.
+ *   The VA is also returned as-is if this is a build without
+ *   CONFIG_ARCH_ADDRENV.
+ *
+ * Parameters:
+ *   va    - The virtual address to convert.
+ *
+ * Returned Values:
+ *   The physical address corresponding to the specified VA.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ARCH_ADDRENV
+static uintptr_t virt_to_phys(FAR void *va)
+{
+  FAR struct tcb_s *tcb;
+  FAR arch_addrenv_t *addrenv;
+  uintptr_t page;
+
+  tcb = nxsched_self();
+  addrenv = &tcb->addrenv_curr->addrenv;
+
+  page = up_addrenv_find_page(addrenv, (uintptr_t)va);
+  if (page == 0)
+    {
+      return (uintptr_t)va;
+    }
+
+  return page | ((uintptr_t)va & MM_PGMASK);
+}
+
+/****************************************************************************
+ * Name: safe_va_range
+ *
+ * Description:
+ *   Check whether provided virtual address range belongs to user-owned
+ *   memory. If this function is called from a kernel thread, it returns
+ *   true. If this function is called in a build without CONFIG_ARCH_ADDRENV
+ *   it always returns true.
+ *
+ * Parameters:
+ *   va    - Beginning of address range to check.
+ *   size  - Size of memory to check.
+ *
+ * Returned Values:
+ *   True if the provided address range belongs to the user or the caller is
+ *   a kernel thread. False otherwise.
+ *
+ ****************************************************************************/
+
+static bool safe_va_range(FAR void *va, size_t size)
+{
+  FAR struct tcb_s *tcb;
+  uint8_t ttype;
+
+  tcb = nxsched_self();
+  ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
+
+  if (ttype == TCB_FLAG_TTYPE_KERNEL)
+    {
+      return 1;
+    }
+
+  if (up_addrenv_user_vaddr((uintptr_t)va) &&
+      up_addrenv_user_vaddr((uintptr_t)va + size - 1))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+#else /* !CONFIG_ARCH_ADDRENV */
+#define virt_to_phys(va)                ((uintptr_t)va)
+#define safe_va_range(addr, size)       (true)
+#endif
+
+#ifdef CONFIG_DEV_OPTEE_SMC64
+static int is_optee_api(optee_invoke_fn *invoke_fn)
+{
+  struct arm64_smccc_res res;
+
+  invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+  return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+         res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
+}
+
+static void print_os_revision(optee_invoke_fn *invoke_fn)
+{
+  union os_revision res =
+  {
+    .result =
+    {
+      .build_id = 0
+    }
+  };
+
+  invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.build_id)
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu (%08lx)\n",
+            res.result.major, res.result.minor,
+            res.result.build_id);
+    }
+  else
+    {
+      syslog(LOG_INFO, "OP-TEE: revision %lu.%lu\n",
+            res.result.major, res.result.minor);
+    }
+}
+
+static int api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_calls_revision_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+  return res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+         (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR;
+}
+
+static int exchange_capabilities(optee_invoke_fn *invoke_fn,
+                                 unsigned long *sec_caps)
+{
+  union {
+    struct arm64_smccc_res smccc;
+    struct optee_smc_exchange_capabilities_result result;
+  } res;
+
+  invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES,
+            OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0,
+            &res.smccc);
+
+  if (res.result.status != OPTEE_SMC_RETURN_OK)
+    {
+      return 0;
+    }
+
+  *sec_caps = res.result.capabilities;
+
+  return 1;
+}
+
+/****************************************************************************
+ * Name: reg_pair_to_ptr
+ *
+ * Description:
+ *   Make a pointer of 2 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of the pointer
+ *   reg1   - Low bits of the pointer
+ *
+ * Returned Values:
+ *    The combined result. Note that if a pointer is 32-bit wide `reg0`
+ *    will be discarded.
+ *
+ ****************************************************************************/
+
+static void *reg_pair_to_ptr(uint32_t reg0, uint32_t reg1)
+{
+  return (void *)(uintptr_t)(((uint64_t)reg0 << 32) | reg1);
+}
+
+/****************************************************************************
+ * Name: reg_pair_from_64
+ *
+ * Description:
+ *   Split a 64-bit value into two 32-bit values
+ *
+ * Parameters:
+ *   reg0   - High bits of `val`
+ *   reg1   - Low bits of `val`
+ *   val    - The value to split
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void reg_pair_from_64(uint32_t *reg0, uint32_t *reg1, uint64_t val)
+{
+  *reg0 = val >> 32;
+  *reg1 = val;
+}
+
+/****************************************************************************
+ * Name: dcache_enabled
+ *
+ * Description:
+ *   Return arm64 EL1 D-Cache status. This should probably be re-located in
+ *   arm64_cache.c once respective implementations for other archs are
+ *   provided.
+ *
+ * Parameters:
+ *   None
+ *
+ * Returned Values:
+ *   0 if CONFIG_ARM64_DCACHE_DISABLE is set, or EL1 D-Cache is not enabled.
+ *   Non-zero otherwise.
+ *
+ ****************************************************************************/
+
+static int dcache_enabled(void)
+{
+#ifdef CONFIG_ARM64_DCACHE_DISABLE
+  return 0;
+#else
+
+  /* arm64_cache.c assumes EL1 all around, so do we.
+   * NuttX doesn't support EL2 yet
+   */
+
+  uint64_t value = read_sysreg(sctlr_el1);
+  return (value & SCTLR_C_BIT) != 0;
+#endif
+}
+
+/****************************************************************************
+ * Name: flush_shm_dcache
+ *
+ * Description:
+ *   Clean and invalidate shared memory D cache on OP-TEE message arguments
+ *   and OP-TEE shared memory allocations registered in the driver's private
+ *   data linked list.
+ *
+ * Parameters:
+ *   priv  - the driver's private data structure
+ *   arg   - the OP-TEE message arguments to flush
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static void flush_shm_dcache(FAR struct optee_priv_data *priv,
+                             FAR struct optee_msg_arg *arg)
+{
+  struct optee_shm_entry *shme;
+  size_t sz = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
+
+  up_flush_dcache((uintptr_t)arg, (uintptr_t)arg + sz);
+
+  SLIST_FOREACH(shme, &priv->list_shm, link)
+    {
+      up_flush_dcache((uintptr_t)shme->shm.addr,
+                      (uintptr_t)shme->shm.addr + shme->shm.length);
+    }
+}
+
+static void handle_rpc(FAR struct optee_priv_data *priv,
+                       FAR struct rpc_param *param)
+{
+  FAR struct optee_shm_entry *shme;
+
+  switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0))
+    {
+      case OPTEE_SMC_RPC_FUNC_ALLOC:
+        if (!optee_shm_add(priv, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
+              param->a1, TEE_SHM_ALLOC | TEE_SHM_REGISTER,
+              &shme))
+          {
+            reg_pair_from_64(&param->a1, &param->a2,
+                virt_to_phys((void *)(uintptr_t)shme->shm.addr));
+
+            /* "cookie" */
+
+            reg_pair_from_64(&param->a4, &param->a5, (uintptr_t)shme);
+          }
+        else
+          {
+            param->a1 = 0;
+            param->a2 = 0;
+            param->a4 = 0;
+            param->a5 = 0;
+          }
+        break;
+      case OPTEE_SMC_RPC_FUNC_FREE:
+        shme = reg_pair_to_ptr(param->a1, param->a2);
+        optee_shm_free(shme);
+        break;
+      case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
+        break;
+      case OPTEE_SMC_RPC_FUNC_CMD:
+        shme = reg_pair_to_ptr(param->a1, param->a2);
+
+        /* optee_suppl_cmd(priv, shme, page_list); */
+
+        syslog(LOG_ERR, "OP-TEE RPC handling of supplicant commands not "
+                        "implemented");
+        break;
+      default:
+        break;
+    }
+
+  param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+}
+
+static int call_err_to_res(uint32_t call_err)
+{
+  switch (call_err)
+    {
+      case OPTEE_SMC_RETURN_OK:
+        return TEE_SUCCESS;
+      default:
+        return (int)call_err;
+    }
+}
+
+static int optee_smc64_call(FAR struct optee_priv_data *priv,
+                            FAR struct optee_msg_arg *arg)
+{
+  struct arm64_smccc_res res;
+  struct rpc_param param =
+  {
+    .a0 = OPTEE_SMC_CALL_WITH_ARG
+  };
+
+  reg_pair_from_64(&param.a1, &param.a2, virt_to_phys(arg));
+
+  while (1)
+    {
+      memset(&res, 0, sizeof(struct arm64_smccc_res));
+
+      /* If cache is off from NuttX, sync the cache shared with OP-TEE */
+
+      if (!dcache_enabled())
+        {
+          flush_shm_dcache(priv, arg);
+        }
+
+      priv->invoke_fn(param.a0, param.a1, param.a2, param.a3,
+                      param.a4, param.a5, param.a6, param.a7, &res);
+
+      /* If cache is off from NuttX, sync the cache shared with OP-TEE */
+
+      if (!dcache_enabled())
+        {
+          flush_shm_dcache(priv, arg);
+        }
+
+      if (OPTEE_SMC_RETURN_IS_RPC(res.a0))
+        {
+          param.a0 = res.a0;
+          param.a1 = res.a1;
+          param.a2 = res.a2;
+          param.a3 = res.a3;
+          handle_rpc(priv, &param);
+        }
+      else
+        {
+          /* TODO:
+           * In case we've accessed RPMB to serve an RPC
+           * request we need to restore the previously
+           * selected partition as the caller may expect it
+           * to remain unchanged.
+           */
+
+          /* optee_suppl_rpmb_release(priv); */
+
+          return call_err_to_res(res.a0);
+        }
+    }
+}
+
+#else /* !CONFIG_DEV_OPTEE_SMC64 */
+
+static int optee_recv(FAR struct socket *psock, FAR void *msg, size_t size)
+{
+  while (size > 0)
+    {
+      ssize_t n = psock_recv(psock, msg, size, 0);
+      if (n <= 0)
+        {
+          return n < 0 ? n : -EIO;
+        }
+
+      size -= n;
+      msg = (FAR char *)msg + n;
+    }
+
+  return 0;
+}
+
+static int optee_send_recv(FAR struct socket *psocket,
+                           FAR struct optee_msg_arg *arg)
+{
+  /* iov[0]: struct opteee_msg_arg + struct optee_msg_param[n]
+   * iov[1 - n+1]: shm_mem
+   * 0 <= n <= 6
+   */
+
+  size_t arg_size = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
+  size_t shm_size[OPTEE_MAX_PARAM_NUM];
+  size_t shm_addr[OPTEE_MAX_PARAM_NUM];
+  struct iovec iov[OPTEE_MAX_IOVEC_NUM];
+  struct msghdr msghdr;
+  unsigned long iovlen = 1;
+  unsigned long i;
+  int ret;
+
+  memset(iov, 0, sizeof(iov));
+  memset(shm_size, 0, sizeof(shm_size));
+
+  iov[0].iov_base = arg;
+  iov[0].iov_len = arg_size;
+
+  for (i = 0; i < arg->num_params; i++)
+    {
+      if (arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
+          arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_INOUT)
+        {
+          iov[iovlen].iov_base =
+            (FAR void *)(uintptr_t)arg->params[i].u.rmem.shm_ref;
+          iov[iovlen].iov_len = arg->params[i].u.rmem.size;
+          shm_size[i] = arg->params[i].u.rmem.size;
+          shm_addr[i] = arg->params[i].u.rmem.shm_ref;
+          iovlen++;
+        }
+      else if (arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT)
+        {
+          shm_size[i] = arg->params[i].u.rmem.size;
+          shm_addr[i] = arg->params[i].u.rmem.shm_ref;
+        }
+    }
+
+  memset(&msghdr, 0, sizeof(struct msghdr));
+  msghdr.msg_iov = iov;
+  msghdr.msg_iovlen = iovlen;
+
+  ret = psock_sendmsg(psocket, &msghdr, 0);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = optee_recv(psocket, arg, arg_size);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  for (i = 0; i < arg->num_params; i++)
+    {
+      if (arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT ||
+          arg->params[i].attr == OPTEE_MSG_ATTR_TYPE_RMEM_INOUT)
+        {
+          size_t size = MIN(arg->params[i].u.rmem.size, shm_size[i]);
+          arg->params[i].u.rmem.shm_ref = shm_addr[i];
+          ret = optee_recv(psocket,
+                           (FAR void *)(uintptr_t)
+                           arg->params[i].u.rmem.shm_ref, size);
+          if (ret < 0)
+            {
+              return ret;
+            }
+        }
+    }
+
+  return 0;
+}
+#endif /* CONFIG_DEV_OPTEE_SMC64 */
+
+/****************************************************************************
+ * Name: optee_alloc_and_init_page_list
+ *
+ * Description:
+ *   Provide page list of memory buffer. Secure world doesn't share mapping
+ *   with Normal world (NuttX in this case) so physical pointers are needed
+ *   when sharing pointers.
+ *
+ * Parameters:
+ *   buf           - Start of buffer
+ *   len           - Length of buffer
+ *   phys_buf_ptr  - Physical pointer with coded offset to page list
+ *
+ * Returned Values:
+ *   A pointer page list on success; NULL on failure
+ *
+ *
+ ****************************************************************************/
+
+FAR void *
+optee_alloc_and_init_page_list(FAR void *buf, size_t len,
+                               FAR uintptr_t *phys_buf_ptr)
+{
+  const unsigned int page_size = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+  const uintptr_t page_mask = page_size - 1;
+  FAR uint8_t *buf_base;
+  unsigned int page_offset;
+  unsigned int num_pages;
+  unsigned int list_size;
+  unsigned int n;
+  FAR void *page_list;
+  FAR struct page_data *pages_data;

Review Comment:
   ```suggestion
     FAR struct page_data *page_data;
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to