Merge tag 'xilinx-for-v2021.04-rc3' of https://gitlab.denx.de/u-boot/custodians/u...
[platform/kernel/u-boot.git] / drivers / tee / optee / supplicant.c
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018, Linaro Limited
4  */
5
6 #include <common.h>
7 #include <log.h>
8 #include <malloc.h>
9 #include <tee.h>
10 #include <linux/types.h>
11
12 #include "optee_msg.h"
13 #include "optee_msg_supplicant.h"
14 #include "optee_private.h"
15 #include "optee_smc.h"
16
17 static void cmd_shm_alloc(struct udevice *dev, struct optee_msg_arg *arg,
18                           void **page_list)
19 {
20         int rc;
21         struct tee_shm *shm;
22         void *pl;
23         u64 ph_ptr;
24
25         arg->ret_origin = TEE_ORIGIN_COMMS;
26
27         if (arg->num_params != 1 ||
28             arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
29                 arg->ret = TEE_ERROR_BAD_PARAMETERS;
30                 return;
31         }
32
33         rc = __tee_shm_add(dev, 0, NULL, arg->params[0].u.value.b,
34                            TEE_SHM_REGISTER | TEE_SHM_ALLOC, &shm);
35         if (rc) {
36                 if (rc == -ENOMEM)
37                         arg->ret = TEE_ERROR_OUT_OF_MEMORY;
38                 else
39                         arg->ret = TEE_ERROR_GENERIC;
40                 return;
41         }
42
43         pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr);
44         if (!pl) {
45                 arg->ret = TEE_ERROR_OUT_OF_MEMORY;
46                 tee_shm_free(shm);
47                 return;
48         }
49
50         *page_list = pl;
51         arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
52                               OPTEE_MSG_ATTR_NONCONTIG;
53         arg->params[0].u.tmem.buf_ptr = ph_ptr;
54         arg->params[0].u.tmem.size = shm->size;
55         arg->params[0].u.tmem.shm_ref = (ulong)shm;
56         arg->ret = TEE_SUCCESS;
57 }
58
59 static void cmd_shm_free(struct optee_msg_arg *arg)
60 {
61         arg->ret_origin = TEE_ORIGIN_COMMS;
62
63         if (arg->num_params != 1 ||
64             arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
65                 arg->ret = TEE_ERROR_BAD_PARAMETERS;
66                 return;
67         }
68
69         tee_shm_free((struct tee_shm *)(ulong)arg->params[0].u.value.b);
70         arg->ret = TEE_SUCCESS;
71 }
72
73 void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
74                      void **page_list)
75 {
76         struct optee_msg_arg *arg = shm_arg->addr;
77
78         switch (arg->cmd) {
79         case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
80                 cmd_shm_alloc(dev, arg, page_list);
81                 break;
82         case OPTEE_MSG_RPC_CMD_SHM_FREE:
83                 cmd_shm_free(arg);
84                 break;
85         case OPTEE_MSG_RPC_CMD_FS:
86                 debug("REE FS storage isn't available\n");
87                 arg->ret = TEE_ERROR_STORAGE_NOT_AVAILABLE;
88                 break;
89         case OPTEE_MSG_RPC_CMD_RPMB:
90                 optee_suppl_cmd_rpmb(dev, arg);
91                 break;
92         case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
93                 optee_suppl_cmd_i2c_transfer(arg);
94                 break;
95         default:
96                 arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
97         }
98
99         arg->ret_origin = TEE_ORIGIN_COMMS;
100 }