xref: /optee_os/core/pta/device.c (revision b89bfe574434d89544f2b857eb7d7871eb19e92c)
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/tee_fs.h>
19 #include <tee/uuid.h>
20 #include <user_ta_header.h>
21 
22 #define PTA_NAME "device.pta"
23 
add_ta(uint32_t flags,const TEE_UUID * uuid,uint8_t * buf,uint32_t blen,uint32_t * pos,uint32_t rflags)24 static void add_ta(uint32_t flags, const TEE_UUID *uuid, uint8_t *buf,
25 		   uint32_t blen, uint32_t *pos, uint32_t rflags)
26 {
27 	flags &= (TA_FLAG_DEVICE_ENUM | TA_FLAG_DEVICE_ENUM_SUPP |
28 		  TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE);
29 	if (flags && flags != TA_FLAG_DEVICE_ENUM &&
30 	    flags != TA_FLAG_DEVICE_ENUM_SUPP &&
31 	    flags != TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE) {
32 		EMSG(PTA_NAME ": skipping TA %pUl, inconsistent flags", uuid);
33 		return;
34 	}
35 
36 	if (flags & rflags) {
37 		if (*pos + sizeof(*uuid) <= blen)
38 			tee_uuid_to_octets(buf + *pos, uuid);
39 
40 		*pos += sizeof(*uuid);
41 	}
42 }
43 
get_devices(uint32_t types,TEE_Param params[TEE_NUM_PARAMS],uint32_t rflags)44 static TEE_Result get_devices(uint32_t types,
45 			      TEE_Param params[TEE_NUM_PARAMS],
46 			      uint32_t rflags)
47 {
48 	const struct pseudo_ta_head *ta = NULL;
49 	const struct embedded_ts *eta = NULL;
50 	void *buf = NULL;
51 	uint32_t blen = 0;
52 	uint32_t pos = 0;
53 
54 	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
55 				     TEE_PARAM_TYPE_NONE,
56 				     TEE_PARAM_TYPE_NONE,
57 				     TEE_PARAM_TYPE_NONE))
58 		return TEE_ERROR_BAD_PARAMETERS;
59 
60 	if (!params[0].memref.buffer && (params[0].memref.size > 0))
61 		return TEE_ERROR_BAD_PARAMETERS;
62 
63 	buf =  params[0].memref.buffer;
64 	blen = params[0].memref.size;
65 
66 	SCATTERED_ARRAY_FOREACH(ta, pseudo_tas, struct pseudo_ta_head)
67 		add_ta(ta->flags, &ta->uuid, buf, blen, &pos, rflags);
68 
69 	if (stmm_get_uuid())
70 		add_ta(TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE,
71 		       stmm_get_uuid(), buf, blen, &pos, rflags);
72 
73 	if (IS_ENABLED(CFG_EARLY_TA))
74 		for_each_early_ta(eta)
75 			add_ta(eta->flags, &eta->uuid, buf, blen, &pos,
76 			       rflags);
77 
78 	params[0].memref.size = pos;
79 	if (pos > blen)
80 		return TEE_ERROR_SHORT_BUFFER;
81 
82 	return TEE_SUCCESS;
83 }
84 
invoke_command(void * pSessionContext __unused,uint32_t nCommandID,uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS])85 static TEE_Result invoke_command(void *pSessionContext __unused,
86 				 uint32_t nCommandID, uint32_t nParamTypes,
87 				 TEE_Param pParams[TEE_NUM_PARAMS])
88 {
89 	TEE_Result res = TEE_SUCCESS;
90 	uint32_t rflags = 0;
91 	/*
92 	 * This should also be true if CFG_RPMB_ANNOUNCE_PROBE_CAP is
93 	 * enabled when the kernel does not support OP-TEE RPMB operations.
94 	 */
95 	bool rpmb_needs_supp = !IS_ENABLED(CFG_RPMB_ANNOUNCE_PROBE_CAP);
96 
97 	switch (nCommandID) {
98 	case PTA_CMD_GET_DEVICES:
99 		rflags = TA_FLAG_DEVICE_ENUM;
100 		break;
101 	case PTA_CMD_GET_DEVICES_SUPP:
102 		rflags = TA_FLAG_DEVICE_ENUM_SUPP;
103 		if (IS_ENABLED(CFG_REE_FS) ||
104 		    (IS_ENABLED(CFG_RPMB_FS) && rpmb_needs_supp))
105 			rflags |= TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE;
106 		break;
107 	case PTA_CMD_GET_DEVICES_RPMB:
108 		if (!IS_ENABLED(CFG_REE_FS)) {
109 			res = tee_rpmb_reinit();
110 			if (res)
111 				return TEE_ERROR_STORAGE_NOT_AVAILABLE;
112 			rflags = TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE;
113 		}
114 		break;
115 	default:
116 		return TEE_ERROR_NOT_IMPLEMENTED;
117 	}
118 
119 	return get_devices(nParamTypes, pParams, rflags);
120 }
121 
122 pseudo_ta_register(.uuid = PTA_DEVICE_UUID, .name = PTA_NAME,
123 		   .flags = PTA_DEFAULT_FLAGS,
124 		   .invoke_command_entry_point = invoke_command);
125