xref: /openbmc/u-boot/drivers/tee/tee-uclass.c (revision 1cc8cc4e675e32cde76487292c8bace5fa927eee)
19ff4a311SJens Wiklander // SPDX-License-Identifier: GPL-2.0+
29ff4a311SJens Wiklander /*
39ff4a311SJens Wiklander  * Copyright (c) 2018 Linaro Limited
49ff4a311SJens Wiklander  */
59ff4a311SJens Wiklander 
69ff4a311SJens Wiklander #include <common.h>
79ff4a311SJens Wiklander #include <dm.h>
89ff4a311SJens Wiklander #include <dm/device-internal.h>
99ff4a311SJens Wiklander #include <dm/uclass-internal.h>
109ff4a311SJens Wiklander #include <tee.h>
119ff4a311SJens Wiklander 
129ff4a311SJens Wiklander /**
139ff4a311SJens Wiklander  * struct tee_uclass_priv - information of a TEE, stored by the uclass
149ff4a311SJens Wiklander  *
159ff4a311SJens Wiklander  * @list_shm:	list of structe tee_shm representing memory blocks shared
169ff4a311SJens Wiklander  *		with the TEE.
179ff4a311SJens Wiklander  */
189ff4a311SJens Wiklander struct tee_uclass_priv {
199ff4a311SJens Wiklander 	struct list_head list_shm;
209ff4a311SJens Wiklander };
219ff4a311SJens Wiklander 
tee_get_ops(struct udevice * dev)229ff4a311SJens Wiklander static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
239ff4a311SJens Wiklander {
249ff4a311SJens Wiklander 	return device_get_ops(dev);
259ff4a311SJens Wiklander }
269ff4a311SJens Wiklander 
tee_get_version(struct udevice * dev,struct tee_version_data * vers)279ff4a311SJens Wiklander void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
289ff4a311SJens Wiklander {
299ff4a311SJens Wiklander 	tee_get_ops(dev)->get_version(dev, vers);
309ff4a311SJens Wiklander }
319ff4a311SJens Wiklander 
tee_open_session(struct udevice * dev,struct tee_open_session_arg * arg,uint num_param,struct tee_param * param)329ff4a311SJens Wiklander int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
339ff4a311SJens Wiklander 		     uint num_param, struct tee_param *param)
349ff4a311SJens Wiklander {
359ff4a311SJens Wiklander 	return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
369ff4a311SJens Wiklander }
379ff4a311SJens Wiklander 
tee_close_session(struct udevice * dev,u32 session)389ff4a311SJens Wiklander int tee_close_session(struct udevice *dev, u32 session)
399ff4a311SJens Wiklander {
409ff4a311SJens Wiklander 	return tee_get_ops(dev)->close_session(dev, session);
419ff4a311SJens Wiklander }
429ff4a311SJens Wiklander 
tee_invoke_func(struct udevice * dev,struct tee_invoke_arg * arg,uint num_param,struct tee_param * param)439ff4a311SJens Wiklander int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
449ff4a311SJens Wiklander 		    uint num_param, struct tee_param *param)
459ff4a311SJens Wiklander {
469ff4a311SJens Wiklander 	return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
479ff4a311SJens Wiklander }
489ff4a311SJens Wiklander 
__tee_shm_add(struct udevice * dev,ulong align,void * addr,ulong size,u32 flags,struct tee_shm ** shmp)499ff4a311SJens Wiklander int __tee_shm_add(struct udevice *dev, ulong align, void *addr, ulong size,
509ff4a311SJens Wiklander 		  u32 flags, struct tee_shm **shmp)
519ff4a311SJens Wiklander {
529ff4a311SJens Wiklander 	struct tee_shm *shm;
539ff4a311SJens Wiklander 	void *p = addr;
549ff4a311SJens Wiklander 	int rc;
559ff4a311SJens Wiklander 
569ff4a311SJens Wiklander 	if (flags & TEE_SHM_ALLOC) {
579ff4a311SJens Wiklander 		if (align)
589ff4a311SJens Wiklander 			p = memalign(align, size);
599ff4a311SJens Wiklander 		else
609ff4a311SJens Wiklander 			p = malloc(size);
619ff4a311SJens Wiklander 	}
629ff4a311SJens Wiklander 	if (!p)
639ff4a311SJens Wiklander 		return -ENOMEM;
649ff4a311SJens Wiklander 
659ff4a311SJens Wiklander 	shm = calloc(1, sizeof(*shm));
669ff4a311SJens Wiklander 	if (!shm) {
679ff4a311SJens Wiklander 		rc = -ENOMEM;
689ff4a311SJens Wiklander 		goto err;
699ff4a311SJens Wiklander 	}
709ff4a311SJens Wiklander 
719ff4a311SJens Wiklander 	shm->dev = dev;
729ff4a311SJens Wiklander 	shm->addr = p;
739ff4a311SJens Wiklander 	shm->size = size;
749ff4a311SJens Wiklander 	shm->flags = flags;
759ff4a311SJens Wiklander 
769ff4a311SJens Wiklander 	if (flags & TEE_SHM_SEC_REGISTER) {
779ff4a311SJens Wiklander 		rc = tee_get_ops(dev)->shm_register(dev, shm);
789ff4a311SJens Wiklander 		if (rc)
799ff4a311SJens Wiklander 			goto err;
809ff4a311SJens Wiklander 	}
819ff4a311SJens Wiklander 
829ff4a311SJens Wiklander 	if (flags & TEE_SHM_REGISTER) {
839ff4a311SJens Wiklander 		struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
849ff4a311SJens Wiklander 
859ff4a311SJens Wiklander 		list_add(&shm->link, &priv->list_shm);
869ff4a311SJens Wiklander 	}
879ff4a311SJens Wiklander 
889ff4a311SJens Wiklander 	*shmp = shm;
899ff4a311SJens Wiklander 
909ff4a311SJens Wiklander 	return 0;
919ff4a311SJens Wiklander err:
929ff4a311SJens Wiklander 	free(shm);
939ff4a311SJens Wiklander 	if (flags & TEE_SHM_ALLOC)
949ff4a311SJens Wiklander 		free(p);
959ff4a311SJens Wiklander 
969ff4a311SJens Wiklander 	return rc;
979ff4a311SJens Wiklander }
989ff4a311SJens Wiklander 
tee_shm_alloc(struct udevice * dev,ulong size,u32 flags,struct tee_shm ** shmp)999ff4a311SJens Wiklander int tee_shm_alloc(struct udevice *dev, ulong size, u32 flags,
1009ff4a311SJens Wiklander 		  struct tee_shm **shmp)
1019ff4a311SJens Wiklander {
1029ff4a311SJens Wiklander 	u32 f = flags;
1039ff4a311SJens Wiklander 
1049ff4a311SJens Wiklander 	f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
1059ff4a311SJens Wiklander 
1069ff4a311SJens Wiklander 	return __tee_shm_add(dev, 0, NULL, size, f, shmp);
1079ff4a311SJens Wiklander }
1089ff4a311SJens Wiklander 
tee_shm_register(struct udevice * dev,void * addr,ulong size,u32 flags,struct tee_shm ** shmp)1099ff4a311SJens Wiklander int tee_shm_register(struct udevice *dev, void *addr, ulong size, u32 flags,
1109ff4a311SJens Wiklander 		     struct tee_shm **shmp)
1119ff4a311SJens Wiklander {
1129ff4a311SJens Wiklander 	u32 f = flags & ~TEE_SHM_ALLOC;
1139ff4a311SJens Wiklander 
1149ff4a311SJens Wiklander 	f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
1159ff4a311SJens Wiklander 
1169ff4a311SJens Wiklander 	return __tee_shm_add(dev, 0, addr, size, f, shmp);
1179ff4a311SJens Wiklander }
1189ff4a311SJens Wiklander 
tee_shm_free(struct tee_shm * shm)1199ff4a311SJens Wiklander void tee_shm_free(struct tee_shm *shm)
1209ff4a311SJens Wiklander {
1219ff4a311SJens Wiklander 	if (!shm)
1229ff4a311SJens Wiklander 		return;
1239ff4a311SJens Wiklander 
1249ff4a311SJens Wiklander 	if (shm->flags & TEE_SHM_SEC_REGISTER)
1259ff4a311SJens Wiklander 		tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
1269ff4a311SJens Wiklander 
1279ff4a311SJens Wiklander 	if (shm->flags & TEE_SHM_REGISTER)
1289ff4a311SJens Wiklander 		list_del(&shm->link);
1299ff4a311SJens Wiklander 
1309ff4a311SJens Wiklander 	if (shm->flags & TEE_SHM_ALLOC)
1319ff4a311SJens Wiklander 		free(shm->addr);
1329ff4a311SJens Wiklander 
1339ff4a311SJens Wiklander 	free(shm);
1349ff4a311SJens Wiklander }
1359ff4a311SJens Wiklander 
tee_shm_is_registered(struct tee_shm * shm,struct udevice * dev)1369ff4a311SJens Wiklander bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
1379ff4a311SJens Wiklander {
1389ff4a311SJens Wiklander 	struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
1399ff4a311SJens Wiklander 	struct tee_shm *s;
1409ff4a311SJens Wiklander 
1419ff4a311SJens Wiklander 	list_for_each_entry(s, &priv->list_shm, link)
1429ff4a311SJens Wiklander 		if (s == shm)
1439ff4a311SJens Wiklander 			return true;
1449ff4a311SJens Wiklander 
1459ff4a311SJens Wiklander 	return false;
1469ff4a311SJens Wiklander }
1479ff4a311SJens Wiklander 
tee_find_device(struct udevice * start,int (* match)(struct tee_version_data * vers,const void * data),const void * data,struct tee_version_data * vers)1489ff4a311SJens Wiklander struct udevice *tee_find_device(struct udevice *start,
1499ff4a311SJens Wiklander 				int (*match)(struct tee_version_data *vers,
1509ff4a311SJens Wiklander 					     const void *data),
1519ff4a311SJens Wiklander 				const void *data,
1529ff4a311SJens Wiklander 				struct tee_version_data *vers)
1539ff4a311SJens Wiklander {
1549ff4a311SJens Wiklander 	struct udevice *dev = start;
1559ff4a311SJens Wiklander 	struct tee_version_data lv;
1569ff4a311SJens Wiklander 	struct tee_version_data *v = vers ? vers : &lv;
1579ff4a311SJens Wiklander 
1589ff4a311SJens Wiklander 	if (!dev)
1599ff4a311SJens Wiklander 		uclass_find_first_device(UCLASS_TEE, &dev);
1609ff4a311SJens Wiklander 	else
1619ff4a311SJens Wiklander 		uclass_find_next_device(&dev);
1629ff4a311SJens Wiklander 
1639ff4a311SJens Wiklander 	for (; dev; uclass_find_next_device(&dev)) {
1649ff4a311SJens Wiklander 		if (device_probe(dev))
1659ff4a311SJens Wiklander 			continue;
1669ff4a311SJens Wiklander 		tee_get_ops(dev)->get_version(dev, v);
1679ff4a311SJens Wiklander 		if (!match || match(v, data))
1689ff4a311SJens Wiklander 			return dev;
1699ff4a311SJens Wiklander 	}
1709ff4a311SJens Wiklander 
1719ff4a311SJens Wiklander 	return NULL;
1729ff4a311SJens Wiklander }
1739ff4a311SJens Wiklander 
tee_pre_probe(struct udevice * dev)1749ff4a311SJens Wiklander static int tee_pre_probe(struct udevice *dev)
1759ff4a311SJens Wiklander {
1769ff4a311SJens Wiklander 	struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
1779ff4a311SJens Wiklander 
1789ff4a311SJens Wiklander 	INIT_LIST_HEAD(&priv->list_shm);
1799ff4a311SJens Wiklander 
1809ff4a311SJens Wiklander 	return 0;
1819ff4a311SJens Wiklander }
1829ff4a311SJens Wiklander 
tee_pre_remove(struct udevice * dev)1839ff4a311SJens Wiklander static int tee_pre_remove(struct udevice *dev)
1849ff4a311SJens Wiklander {
1859ff4a311SJens Wiklander 	struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
1869ff4a311SJens Wiklander 	struct tee_shm *shm;
1879ff4a311SJens Wiklander 
1889ff4a311SJens Wiklander 	/*
1899ff4a311SJens Wiklander 	 * Any remaining shared memory must be unregistered now as U-Boot
1909ff4a311SJens Wiklander 	 * is about to hand over to the next stage and that memory will be
1919ff4a311SJens Wiklander 	 * reused.
1929ff4a311SJens Wiklander 	 */
1939ff4a311SJens Wiklander 	while (!list_empty(&priv->list_shm)) {
1949ff4a311SJens Wiklander 		shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
1959ff4a311SJens Wiklander 		debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
1969ff4a311SJens Wiklander 		      __func__, (void *)shm, shm->size, shm->flags);
1979ff4a311SJens Wiklander 		tee_shm_free(shm);
1989ff4a311SJens Wiklander 	}
1999ff4a311SJens Wiklander 
2009ff4a311SJens Wiklander 	return 0;
2019ff4a311SJens Wiklander }
2029ff4a311SJens Wiklander 
2039ff4a311SJens Wiklander UCLASS_DRIVER(tee) = {
2049ff4a311SJens Wiklander 	.id = UCLASS_TEE,
2059ff4a311SJens Wiklander 	.name = "tee",
2069ff4a311SJens Wiklander 	.per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
2079ff4a311SJens Wiklander 	.pre_probe = tee_pre_probe,
2089ff4a311SJens Wiklander 	.pre_remove = tee_pre_remove,
2099ff4a311SJens Wiklander };
210*1cc8cc4eSJens Wiklander 
tee_optee_ta_uuid_from_octets(struct tee_optee_ta_uuid * d,const u8 s[TEE_UUID_LEN])211*1cc8cc4eSJens Wiklander void tee_optee_ta_uuid_from_octets(struct tee_optee_ta_uuid *d,
212*1cc8cc4eSJens Wiklander 				   const u8 s[TEE_UUID_LEN])
213*1cc8cc4eSJens Wiklander {
214*1cc8cc4eSJens Wiklander 	d->time_low = ((u32)s[0] << 24) | ((u32)s[1] << 16) |
215*1cc8cc4eSJens Wiklander 		      ((u32)s[2] << 8) | s[3],
216*1cc8cc4eSJens Wiklander 	d->time_mid = ((u32)s[4] << 8) | s[5];
217*1cc8cc4eSJens Wiklander 	d->time_hi_and_version = ((u32)s[6] << 8) | s[7];
218*1cc8cc4eSJens Wiklander 	memcpy(d->clock_seq_and_node, s + 8, sizeof(d->clock_seq_and_node));
219*1cc8cc4eSJens Wiklander }
220*1cc8cc4eSJens Wiklander 
tee_optee_ta_uuid_to_octets(u8 d[TEE_UUID_LEN],const struct tee_optee_ta_uuid * s)221*1cc8cc4eSJens Wiklander void tee_optee_ta_uuid_to_octets(u8 d[TEE_UUID_LEN],
222*1cc8cc4eSJens Wiklander 				 const struct tee_optee_ta_uuid *s)
223*1cc8cc4eSJens Wiklander {
224*1cc8cc4eSJens Wiklander 	d[0] = s->time_low >> 24;
225*1cc8cc4eSJens Wiklander 	d[1] = s->time_low >> 16;
226*1cc8cc4eSJens Wiklander 	d[2] = s->time_low >> 8;
227*1cc8cc4eSJens Wiklander 	d[3] = s->time_low;
228*1cc8cc4eSJens Wiklander 	d[4] = s->time_mid >> 8;
229*1cc8cc4eSJens Wiklander 	d[5] = s->time_mid;
230*1cc8cc4eSJens Wiklander 	d[6] = s->time_hi_and_version >> 8;
231*1cc8cc4eSJens Wiklander 	d[7] = s->time_hi_and_version;
232*1cc8cc4eSJens Wiklander 	memcpy(d + 8, s->clock_seq_and_node, sizeof(s->clock_seq_and_node));
233*1cc8cc4eSJens Wiklander }
234