brintos

brintos / linux-shallow public Read only

0
0
Text · 6.8 KiB · 40e3183 Raw
287 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2019 Broadcom.4 */5 6#include <linux/kernel.h>7#include <linux/module.h>8#include <linux/sizes.h>9#include <linux/slab.h>10#include <linux/tee_drv.h>11#include <linux/uuid.h>12 13#include <linux/firmware/broadcom/tee_bnxt_fw.h>14 15#define MAX_SHM_MEM_SZ	SZ_4M16 17#define MAX_TEE_PARAM_ARRY_MEMB		418 19enum ta_cmd {20	/*21	 * TA_CMD_BNXT_FASTBOOT - boot bnxt device by copying f/w into sram22	 *23	 *	param[0] unused24	 *	param[1] unused25	 *	param[2] unused26	 *	param[3] unused27	 *28	 * Result:29	 *	TEE_SUCCESS - Invoke command success30	 *	TEE_ERROR_ITEM_NOT_FOUND - Corrupt f/w image found on memory31	 */32	TA_CMD_BNXT_FASTBOOT = 0,33 34	/*35	 * TA_CMD_BNXT_COPY_COREDUMP - copy the core dump into shm36	 *37	 *	param[0] (inout memref) - Coredump buffer memory reference38	 *	param[1] (in value) - value.a: offset, data to be copied from39	 *			      value.b: size of data to be copied40	 *	param[2] unused41	 *	param[3] unused42	 *43	 * Result:44	 *	TEE_SUCCESS - Invoke command success45	 *	TEE_ERROR_BAD_PARAMETERS - Incorrect input param46	 *	TEE_ERROR_ITEM_NOT_FOUND - Corrupt core dump47	 */48	TA_CMD_BNXT_COPY_COREDUMP = 3,49};50 51/**52 * struct tee_bnxt_fw_private - OP-TEE bnxt private data53 * @dev:		OP-TEE based bnxt device.54 * @ctx:		OP-TEE context handler.55 * @session_id:		TA session identifier.56 */57struct tee_bnxt_fw_private {58	struct device *dev;59	struct tee_context *ctx;60	u32 session_id;61	struct tee_shm *fw_shm_pool;62};63 64static struct tee_bnxt_fw_private pvt_data;65 66static void prepare_args(int cmd,67			 struct tee_ioctl_invoke_arg *arg,68			 struct tee_param *param)69{70	memset(arg, 0, sizeof(*arg));71	memset(param, 0, MAX_TEE_PARAM_ARRY_MEMB * sizeof(*param));72 73	arg->func = cmd;74	arg->session = pvt_data.session_id;75	arg->num_params = MAX_TEE_PARAM_ARRY_MEMB;76 77	/* Fill invoke cmd params */78	switch (cmd) {79	case TA_CMD_BNXT_COPY_COREDUMP:80		param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;81		param[0].u.memref.shm = pvt_data.fw_shm_pool;82		param[0].u.memref.size = MAX_SHM_MEM_SZ;83		param[0].u.memref.shm_offs = 0;84		param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;85		break;86	case TA_CMD_BNXT_FASTBOOT:87	default:88		/* Nothing to do */89		break;90	}91}92 93/**94 * tee_bnxt_fw_load() - Load the bnxt firmware95 *		    Uses an OP-TEE call to start a secure96 *		    boot process.97 * Returns 0 on success, negative errno otherwise.98 */99int tee_bnxt_fw_load(void)100{101	int ret = 0;102	struct tee_ioctl_invoke_arg arg;103	struct tee_param param[MAX_TEE_PARAM_ARRY_MEMB];104 105	if (!pvt_data.ctx)106		return -ENODEV;107 108	prepare_args(TA_CMD_BNXT_FASTBOOT, &arg, param);109 110	ret = tee_client_invoke_func(pvt_data.ctx, &arg, param);111	if (ret < 0 || arg.ret != 0) {112		dev_err(pvt_data.dev,113			"TA_CMD_BNXT_FASTBOOT invoke failed TEE err: %x, ret:%x\n",114			arg.ret, ret);115		return -EINVAL;116	}117 118	return 0;119}120EXPORT_SYMBOL(tee_bnxt_fw_load);121 122/**123 * tee_bnxt_copy_coredump() - Copy coredump from the allocated memory124 *			    Uses an OP-TEE call to copy coredump125 * @buf:	destination buffer where core dump is copied into126 * @offset:	offset from the base address of core dump area127 * @size:	size of the dump128 *129 * Returns 0 on success, negative errno otherwise.130 */131int tee_bnxt_copy_coredump(void *buf, u32 offset, u32 size)132{133	struct tee_ioctl_invoke_arg arg;134	struct tee_param param[MAX_TEE_PARAM_ARRY_MEMB];135	void *core_data;136	u32 rbytes = size;137	u32 nbytes = 0;138	int ret = 0;139 140	if (!pvt_data.ctx)141		return -ENODEV;142 143	prepare_args(TA_CMD_BNXT_COPY_COREDUMP, &arg, param);144 145	while (rbytes)  {146		nbytes = rbytes;147 148		nbytes = min_t(u32, rbytes, param[0].u.memref.size);149 150		/* Fill additional invoke cmd params */151		param[1].u.value.a = offset;152		param[1].u.value.b = nbytes;153 154		ret = tee_client_invoke_func(pvt_data.ctx, &arg, param);155		if (ret < 0 || arg.ret != 0) {156			dev_err(pvt_data.dev,157				"TA_CMD_BNXT_COPY_COREDUMP invoke failed TEE err: %x, ret:%x\n",158				arg.ret, ret);159			return -EINVAL;160		}161 162		core_data = tee_shm_get_va(pvt_data.fw_shm_pool, 0);163		if (IS_ERR(core_data)) {164			dev_err(pvt_data.dev, "tee_shm_get_va failed\n");165			return PTR_ERR(core_data);166		}167 168		memcpy(buf, core_data, nbytes);169 170		rbytes -= nbytes;171		buf += nbytes;172		offset += nbytes;173	}174 175	return 0;176}177EXPORT_SYMBOL(tee_bnxt_copy_coredump);178 179static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)180{181	return (ver->impl_id == TEE_IMPL_ID_OPTEE);182}183 184static int tee_bnxt_fw_probe(struct device *dev)185{186	struct tee_client_device *bnxt_device = to_tee_client_device(dev);187	int ret, err = -ENODEV;188	struct tee_ioctl_open_session_arg sess_arg;189	struct tee_shm *fw_shm_pool;190 191	memset(&sess_arg, 0, sizeof(sess_arg));192 193	/* Open context with TEE driver */194	pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,195					       NULL);196	if (IS_ERR(pvt_data.ctx))197		return -ENODEV;198 199	/* Open session with Bnxt load Trusted App */200	export_uuid(sess_arg.uuid, &bnxt_device->id.uuid);201	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;202	sess_arg.num_params = 0;203 204	ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);205	if (ret < 0 || sess_arg.ret != 0) {206		dev_err(dev, "tee_client_open_session failed, err: %x\n",207			sess_arg.ret);208		err = -EINVAL;209		goto out_ctx;210	}211	pvt_data.session_id = sess_arg.session;212 213	pvt_data.dev = dev;214 215	fw_shm_pool = tee_shm_alloc_kernel_buf(pvt_data.ctx, MAX_SHM_MEM_SZ);216	if (IS_ERR(fw_shm_pool)) {217		dev_err(pvt_data.dev, "tee_shm_alloc_kernel_buf failed\n");218		err = PTR_ERR(fw_shm_pool);219		goto out_sess;220	}221 222	pvt_data.fw_shm_pool = fw_shm_pool;223 224	return 0;225 226out_sess:227	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);228out_ctx:229	tee_client_close_context(pvt_data.ctx);230 231	return err;232}233 234static int tee_bnxt_fw_remove(struct device *dev)235{236	tee_shm_free(pvt_data.fw_shm_pool);237	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);238	tee_client_close_context(pvt_data.ctx);239	pvt_data.ctx = NULL;240 241	return 0;242}243 244static void tee_bnxt_fw_shutdown(struct device *dev)245{246	tee_shm_free(pvt_data.fw_shm_pool);247	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);248	tee_client_close_context(pvt_data.ctx);249	pvt_data.ctx = NULL;250}251 252static const struct tee_client_device_id tee_bnxt_fw_id_table[] = {253	{UUID_INIT(0x6272636D, 0x2019, 0x0716,254		    0x42, 0x43, 0x4D, 0x5F, 0x53, 0x43, 0x48, 0x49)},255	{}256};257 258MODULE_DEVICE_TABLE(tee, tee_bnxt_fw_id_table);259 260static struct tee_client_driver tee_bnxt_fw_driver = {261	.id_table	= tee_bnxt_fw_id_table,262	.driver		= {263		.name		= KBUILD_MODNAME,264		.bus		= &tee_bus_type,265		.probe		= tee_bnxt_fw_probe,266		.remove		= tee_bnxt_fw_remove,267		.shutdown	= tee_bnxt_fw_shutdown,268	},269};270 271static int __init tee_bnxt_fw_mod_init(void)272{273	return driver_register(&tee_bnxt_fw_driver.driver);274}275 276static void __exit tee_bnxt_fw_mod_exit(void)277{278	driver_unregister(&tee_bnxt_fw_driver.driver);279}280 281module_init(tee_bnxt_fw_mod_init);282module_exit(tee_bnxt_fw_mod_exit);283 284MODULE_AUTHOR("Vikas Gupta <vikas.gupta@broadcom.com>");285MODULE_DESCRIPTION("Broadcom bnxt firmware manager");286MODULE_LICENSE("GPL v2");287