mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	tee: add bus driver framework for TEE based devices
Introduce a generic TEE bus driver concept for TEE based kernel drivers which would like to communicate with TEE based devices/services. Also add support in module device table for these new TEE based devices. In this TEE bus concept, devices/services are identified via Universally Unique Identifier (UUID) and drivers register a table of device UUIDs which they can support. So this TEE bus framework registers following apis: - match(): Iterates over the driver UUID table to find a corresponding match for device UUID. If a match is found, then this particular device is probed via corresponding probe api registered by the driver. This process happens whenever a device or a driver is registered with TEE bus. - uevent(): Notifies user-space (udev) whenever a new device is registered on this bus for auto-loading of modularized drivers. Also this framework allows for device enumeration to be specific to corresponding TEE implementation like OP-TEE etc. Signed-off-by: Sumit Garg <sumit.garg@linaro.org> Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org> Reviewed-by: Bhupesh Sharma <bhsharma@redhat.com> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
This commit is contained in:
		
							parent
							
								
									42bf4152d8
								
							
						
					
					
						commit
						0fc1db9d10
					
				
					 5 changed files with 112 additions and 5 deletions
				
			
		|  | @ -15,7 +15,6 @@ | |||
| #define pr_fmt(fmt) "%s: " fmt, __func__ | ||||
| 
 | ||||
| #include <linux/cdev.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/fs.h> | ||||
| #include <linux/idr.h> | ||||
| #include <linux/module.h> | ||||
|  | @ -1040,6 +1039,39 @@ int tee_client_invoke_func(struct tee_context *ctx, | |||
| } | ||||
| EXPORT_SYMBOL_GPL(tee_client_invoke_func); | ||||
| 
 | ||||
| static int tee_client_device_match(struct device *dev, | ||||
| 				   struct device_driver *drv) | ||||
| { | ||||
| 	const struct tee_client_device_id *id_table; | ||||
| 	struct tee_client_device *tee_device; | ||||
| 
 | ||||
| 	id_table = to_tee_client_driver(drv)->id_table; | ||||
| 	tee_device = to_tee_client_device(dev); | ||||
| 
 | ||||
| 	while (!uuid_is_null(&id_table->uuid)) { | ||||
| 		if (uuid_equal(&tee_device->id.uuid, &id_table->uuid)) | ||||
| 			return 1; | ||||
| 		id_table++; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int tee_client_device_uevent(struct device *dev, | ||||
| 				    struct kobj_uevent_env *env) | ||||
| { | ||||
| 	uuid_t *dev_id = &to_tee_client_device(dev)->id.uuid; | ||||
| 
 | ||||
| 	return add_uevent_var(env, "MODALIAS=tee:%pUb", dev_id); | ||||
| } | ||||
| 
 | ||||
| struct bus_type tee_bus_type = { | ||||
| 	.name		= "tee", | ||||
| 	.match		= tee_client_device_match, | ||||
| 	.uevent		= tee_client_device_uevent, | ||||
| }; | ||||
| EXPORT_SYMBOL_GPL(tee_bus_type); | ||||
| 
 | ||||
| static int __init tee_init(void) | ||||
| { | ||||
| 	int rc; | ||||
|  | @ -1053,18 +1085,32 @@ static int __init tee_init(void) | |||
| 	rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee"); | ||||
| 	if (rc) { | ||||
| 		pr_err("failed to allocate char dev region\n"); | ||||
| 		goto out_unreg_class; | ||||
| 	} | ||||
| 
 | ||||
| 	rc = bus_register(&tee_bus_type); | ||||
| 	if (rc) { | ||||
| 		pr_err("failed to register tee bus\n"); | ||||
| 		goto out_unreg_chrdev; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| out_unreg_chrdev: | ||||
| 	unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); | ||||
| out_unreg_class: | ||||
| 	class_destroy(tee_class); | ||||
| 	tee_class = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| static void __exit tee_exit(void) | ||||
| { | ||||
| 	bus_unregister(&tee_bus_type); | ||||
| 	unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); | ||||
| 	class_destroy(tee_class); | ||||
| 	tee_class = NULL; | ||||
| 	unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); | ||||
| } | ||||
| 
 | ||||
| subsys_initcall(tee_init); | ||||
|  |  | |||
|  | @ -779,4 +779,13 @@ struct typec_device_id { | |||
| 	kernel_ulong_t driver_data; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct tee_client_device_id - tee based device identifier | ||||
|  * @uuid: For TEE based client devices we use the device uuid as | ||||
|  *        the identifier. | ||||
|  */ | ||||
| struct tee_client_device_id { | ||||
| 	uuid_t uuid; | ||||
| }; | ||||
| 
 | ||||
| #endif /* LINUX_MOD_DEVICETABLE_H */ | ||||
|  |  | |||
|  | @ -15,11 +15,14 @@ | |||
| #ifndef __TEE_DRV_H | ||||
| #define __TEE_DRV_H | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| #include <linux/device.h> | ||||
| #include <linux/idr.h> | ||||
| #include <linux/kref.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/mod_devicetable.h> | ||||
| #include <linux/tee.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/uuid.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * The file describes the API provided by the generic TEE driver to the | ||||
|  | @ -544,4 +547,31 @@ static inline bool tee_param_is_memref(struct tee_param *param) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| extern struct bus_type tee_bus_type; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct tee_client_device - tee based device | ||||
|  * @id:			device identifier | ||||
|  * @dev:		device structure | ||||
|  */ | ||||
| struct tee_client_device { | ||||
| 	struct tee_client_device_id id; | ||||
| 	struct device dev; | ||||
| }; | ||||
| 
 | ||||
| #define to_tee_client_device(d) container_of(d, struct tee_client_device, dev) | ||||
| 
 | ||||
| /**
 | ||||
|  * struct tee_client_driver - tee client driver | ||||
|  * @id_table:		device id table supported by this driver | ||||
|  * @driver:		driver structure | ||||
|  */ | ||||
| struct tee_client_driver { | ||||
| 	const struct tee_client_device_id *id_table; | ||||
| 	struct device_driver driver; | ||||
| }; | ||||
| 
 | ||||
| #define to_tee_client_driver(d) \ | ||||
| 		container_of(d, struct tee_client_driver, driver) | ||||
| 
 | ||||
| #endif /*__TEE_DRV_H*/ | ||||
|  |  | |||
|  | @ -225,5 +225,8 @@ int main(void) | |||
| 	DEVID_FIELD(typec_device_id, svid); | ||||
| 	DEVID_FIELD(typec_device_id, mode); | ||||
| 
 | ||||
| 	DEVID(tee_client_device_id); | ||||
| 	DEVID_FIELD(tee_client_device_id, uuid); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -37,6 +37,9 @@ typedef unsigned char	__u8; | |||
| typedef struct { | ||||
| 	__u8 b[16]; | ||||
| } uuid_le; | ||||
| typedef struct { | ||||
| 	__u8 b[16]; | ||||
| } uuid_t; | ||||
| 
 | ||||
| /* Big exception to the "don't include kernel headers into userspace, which
 | ||||
|  * even potentially has different endianness and word sizes, since | ||||
|  | @ -1287,6 +1290,21 @@ static int do_typec_entry(const char *filename, void *symval, char *alias) | |||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| /* Looks like: tee:uuid */ | ||||
| static int do_tee_entry(const char *filename, void *symval, char *alias) | ||||
| { | ||||
| 	DEF_FIELD(symval, tee_client_device_id, uuid); | ||||
| 
 | ||||
| 	sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", | ||||
| 		uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4], | ||||
| 		uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9], | ||||
| 		uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14], | ||||
| 		uuid.b[15]); | ||||
| 
 | ||||
| 	add_wildcard(alias); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| /* Does namelen bytes of name exactly match the symbol? */ | ||||
| static bool sym_is(const char *name, unsigned namelen, const char *symbol) | ||||
| { | ||||
|  | @ -1357,6 +1375,7 @@ static const struct devtable devtable[] = { | |||
| 	{"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, | ||||
| 	{"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, | ||||
| 	{"typec", SIZE_typec_device_id, do_typec_entry}, | ||||
| 	{"tee", SIZE_tee_client_device_id, do_tee_entry}, | ||||
| }; | ||||
| 
 | ||||
| /* Create MODULE_ALIAS() statements.
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Sumit Garg
						Sumit Garg