xref: /optee_os/core/pta/device.c (revision af3fb62410645ac9636d27c3d1db72c0c9fca913)
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/stmm_sp.h>
16 #include <kernel/tee_ta_manager.h>
17 #include <pta_device.h>
18 #include <tee/uuid.h>
19 #include <user_ta_header.h>
20 
21 #define PTA_NAME "device.pta"
22 
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 
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 (stmm_get_uuid())
66 		add_ta(TA_FLAG_DEVICE_ENUM_SUPP, stmm_get_uuid(), buf, blen,
67 		       &pos, rflags);
68 
69 	if (IS_ENABLED(CFG_EARLY_TA))
70 		for_each_early_ta(eta)
71 			add_ta(eta->flags, &eta->uuid, buf, blen, &pos,
72 			       rflags);
73 
74 	params[0].memref.size = pos;
75 	if (pos > blen)
76 		return TEE_ERROR_SHORT_BUFFER;
77 
78 	return TEE_SUCCESS;
79 }
80 
81 static TEE_Result invoke_command(void *pSessionContext __unused,
82 				 uint32_t nCommandID, uint32_t nParamTypes,
83 				 TEE_Param pParams[TEE_NUM_PARAMS])
84 {
85 	switch (nCommandID) {
86 	case PTA_CMD_GET_DEVICES:
87 		return get_devices(nParamTypes, pParams,
88 				   TA_FLAG_DEVICE_ENUM);
89 	case PTA_CMD_GET_DEVICES_SUPP:
90 		return get_devices(nParamTypes, pParams,
91 				   TA_FLAG_DEVICE_ENUM_SUPP);
92 	default:
93 		break;
94 	}
95 
96 	return TEE_ERROR_NOT_IMPLEMENTED;
97 }
98 
99 pseudo_ta_register(.uuid = PTA_DEVICE_UUID, .name = PTA_NAME,
100 		   .flags = PTA_DEFAULT_FLAGS,
101 		   .invoke_command_entry_point = invoke_command);
102