1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2019, Linaro Limited
4 */
5
6 /*
7 * This pseudo TA is used by normal world OS TEE driver to fetch pseudo TA's
8 * UUIDs which can act as TEE bus devices.
9 */
10
11 #include <config.h>
12 #include <kernel/early_ta.h>
13 #include <kernel/linker.h>
14 #include <kernel/pseudo_ta.h>
15 #include <kernel/tee_ta_manager.h>
16 #include <pta_device.h>
17 #include <string.h>
18 #include <tee/uuid.h>
19 #include <user_ta_header.h>
20
21 #define PTA_NAME "device.pta"
22
add_ta(uint32_t flags,const TEE_UUID * uuid,uint8_t * buf,uint32_t blen,uint32_t * pos,uint32_t rflags)23 static void add_ta(uint32_t flags, const TEE_UUID *uuid, uint8_t *buf,
24 uint32_t blen, uint32_t *pos, uint32_t rflags)
25 {
26 if ((flags & TA_FLAG_DEVICE_ENUM) &&
27 (flags & TA_FLAG_DEVICE_ENUM_SUPP)) {
28 EMSG(PTA_NAME ": skipping TA %pUl, inconsistent flags", uuid);
29 return;
30 }
31
32 if (flags & rflags) {
33 if (*pos + sizeof(*uuid) <= blen)
34 tee_uuid_to_octets(buf + *pos, uuid);
35
36 *pos += sizeof(*uuid);
37 }
38 }
39
get_devices(uint32_t types,TEE_Param params[TEE_NUM_PARAMS],uint32_t rflags)40 static TEE_Result get_devices(uint32_t types,
41 TEE_Param params[TEE_NUM_PARAMS],
42 uint32_t rflags)
43 {
44 const struct pseudo_ta_head *ta = NULL;
45 const struct embedded_ts *eta = NULL;
46 void *buf = NULL;
47 uint32_t blen = 0;
48 uint32_t pos = 0;
49
50 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
51 TEE_PARAM_TYPE_NONE,
52 TEE_PARAM_TYPE_NONE,
53 TEE_PARAM_TYPE_NONE))
54 return TEE_ERROR_BAD_PARAMETERS;
55
56 if (!params[0].memref.buffer && (params[0].memref.size > 0))
57 return TEE_ERROR_BAD_PARAMETERS;
58
59 buf = params[0].memref.buffer;
60 blen = params[0].memref.size;
61
62 SCATTERED_ARRAY_FOREACH(ta, pseudo_tas, struct pseudo_ta_head)
63 add_ta(ta->flags, &ta->uuid, buf, blen, &pos, rflags);
64
65 if (IS_ENABLED(CFG_EARLY_TA))
66 for_each_early_ta(eta)
67 add_ta(eta->flags, &eta->uuid, buf, blen, &pos,
68 rflags);
69
70 params[0].memref.size = pos;
71 if (pos > blen)
72 return TEE_ERROR_SHORT_BUFFER;
73
74 return TEE_SUCCESS;
75 }
76
invoke_command(void * pSessionContext __unused,uint32_t nCommandID,uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS])77 static TEE_Result invoke_command(void *pSessionContext __unused,
78 uint32_t nCommandID, uint32_t nParamTypes,
79 TEE_Param pParams[TEE_NUM_PARAMS])
80 {
81 switch (nCommandID) {
82 case PTA_CMD_GET_DEVICES:
83 return get_devices(nParamTypes, pParams,
84 TA_FLAG_DEVICE_ENUM);
85 case PTA_CMD_GET_DEVICES_SUPP:
86 return get_devices(nParamTypes, pParams,
87 TA_FLAG_DEVICE_ENUM_SUPP);
88 default:
89 break;
90 }
91
92 return TEE_ERROR_NOT_IMPLEMENTED;
93 }
94
95 pseudo_ta_register(.uuid = PTA_DEVICE_UUID, .name = PTA_NAME,
96 .flags = PTA_DEFAULT_FLAGS,
97 .invoke_command_entry_point = invoke_command);
98