diff options
Diffstat (limited to 'drivers/char/tpm/tpm_ftpm_tee.c')
| -rw-r--r-- | drivers/char/tpm/tpm_ftpm_tee.c | 179 |
1 files changed, 95 insertions, 84 deletions
diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c index 2491a2cb54a2..4e63c30aeaf1 100644 --- a/drivers/char/tpm/tpm_ftpm_tee.c +++ b/drivers/char/tpm/tpm_ftpm_tee.c @@ -11,7 +11,6 @@ #include <linux/acpi.h> #include <linux/of.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/tee_drv.h> #include <linux/tpm.h> @@ -32,45 +31,19 @@ static const uuid_t ftpm_ta_uuid = 0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96); /** - * ftpm_tee_tpm_op_recv() - retrieve fTPM response. - * @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h. - * @buf: the buffer to store data. - * @count: the number of bytes to read. - * - * Return: - * In case of success the number of bytes received. - * On failure, -errno. - */ -static int ftpm_tee_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count) -{ - struct ftpm_tee_private *pvt_data = dev_get_drvdata(chip->dev.parent); - size_t len; - - len = pvt_data->resp_len; - if (count < len) { - dev_err(&chip->dev, - "%s: Invalid size in recv: count=%zd, resp_len=%zd\n", - __func__, count, len); - return -EIO; - } - - memcpy(buf, pvt_data->resp_buf, len); - pvt_data->resp_len = 0; - - return len; -} - -/** - * ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory. + * ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory + * and retrieve the response. * @chip: the tpm_chip description as specified in driver/char/tpm/tpm.h - * @buf: the buffer to send. - * @len: the number of bytes to send. + * @buf: the buffer to send and to store the response. + * @bufsiz: the size of the buffer. + * @cmd_len: the number of bytes to send. * * Return: - * In case of success, returns 0. + * In case of success, returns the number of bytes received. * On failure, -errno */ -static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t len) +static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz, + size_t cmd_len) { struct ftpm_tee_private *pvt_data = dev_get_drvdata(chip->dev.parent); size_t resp_len; @@ -81,16 +54,15 @@ static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t len) struct tee_param command_params[4]; struct tee_shm *shm = pvt_data->shm; - if (len > MAX_COMMAND_SIZE) { + if (cmd_len > MAX_COMMAND_SIZE) { dev_err(&chip->dev, "%s: len=%zd exceeds MAX_COMMAND_SIZE supported by fTPM TA\n", - __func__, len); + __func__, cmd_len); return -EIO; } memset(&transceive_args, 0, sizeof(transceive_args)); memset(command_params, 0, sizeof(command_params)); - pvt_data->resp_len = 0; /* Invoke FTPM_OPTEE_TA_SUBMIT_COMMAND function of fTPM TA */ transceive_args = (struct tee_ioctl_invoke_arg) { @@ -104,7 +76,7 @@ static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t len) .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT, .u.memref = { .shm = shm, - .size = len, + .size = cmd_len, .shm_offs = 0, }, }; @@ -116,7 +88,7 @@ static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t len) return PTR_ERR(temp_buf); } memset(temp_buf, 0, (MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE)); - memcpy(temp_buf, buf, len); + memcpy(temp_buf, buf, cmd_len); command_params[1] = (struct tee_param) { .attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT, @@ -157,38 +129,21 @@ static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t len) __func__, resp_len); return -EIO; } + if (resp_len > bufsiz) { + dev_err(&chip->dev, + "%s: resp_len=%zd exceeds bufsiz=%zd\n", + __func__, resp_len, bufsiz); + return -EIO; + } - /* sanity checks look good, cache the response */ - memcpy(pvt_data->resp_buf, temp_buf, resp_len); - pvt_data->resp_len = resp_len; - - return 0; -} - -static void ftpm_tee_tpm_op_cancel(struct tpm_chip *chip) -{ - /* not supported */ -} + memcpy(buf, temp_buf, resp_len); -static u8 ftpm_tee_tpm_op_status(struct tpm_chip *chip) -{ - return 0; -} - -static bool ftpm_tee_tpm_req_canceled(struct tpm_chip *chip, u8 status) -{ - return 0; + return resp_len; } static const struct tpm_class_ops ftpm_tee_tpm_ops = { .flags = TPM_OPS_AUTO_STARTUP, - .recv = ftpm_tee_tpm_op_recv, .send = ftpm_tee_tpm_op_send, - .cancel = ftpm_tee_tpm_op_cancel, - .status = ftpm_tee_tpm_op_status, - .req_complete_mask = 0, - .req_complete_val = 0, - .req_canceled = ftpm_tee_tpm_req_canceled, }; /* @@ -209,16 +164,15 @@ static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data) /** * ftpm_tee_probe() - initialize the fTPM - * @pdev: the platform_device description. + * @dev: the device description. * * Return: * On success, 0. On failure, -errno. */ -static int ftpm_tee_probe(struct platform_device *pdev) +static int ftpm_tee_probe(struct device *dev) { int rc; struct tpm_chip *chip; - struct device *dev = &pdev->dev; struct ftpm_tee_private *pvt_data = NULL; struct tee_ioctl_open_session_arg sess_arg; @@ -255,11 +209,11 @@ static int ftpm_tee_probe(struct platform_device *pdev) pvt_data->session = sess_arg.session; /* Allocate dynamic shared memory with fTPM TA */ - pvt_data->shm = tee_shm_alloc(pvt_data->ctx, - MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE, - TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); + pvt_data->shm = tee_shm_alloc_kernel_buf(pvt_data->ctx, + MAX_COMMAND_SIZE + + MAX_RESPONSE_SIZE); if (IS_ERR(pvt_data->shm)) { - dev_err(dev, "%s: tee_shm_alloc failed\n", __func__); + dev_err(dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__); rc = -ENOMEM; goto out_shm_alloc; } @@ -273,7 +227,7 @@ static int ftpm_tee_probe(struct platform_device *pdev) } pvt_data->chip = chip; - pvt_data->chip->flags |= TPM_CHIP_FLAG_TPM2; + pvt_data->chip->flags |= TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_SYNC; /* Create a character device for the fTPM */ rc = tpm_chip_register(pvt_data->chip); @@ -297,16 +251,23 @@ out_tee_session: return rc; } +static int ftpm_plat_tee_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + return ftpm_tee_probe(dev); +} + /** * ftpm_tee_remove() - remove the TPM device - * @pdev: the platform_device description. + * @dev: the device description. * * Return: * 0 always. */ -static int ftpm_tee_remove(struct platform_device *pdev) +static int ftpm_tee_remove(struct device *dev) { - struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev); + struct ftpm_tee_private *pvt_data = dev_get_drvdata(dev); /* Release the chip */ tpm_chip_unregister(pvt_data->chip); @@ -328,11 +289,18 @@ static int ftpm_tee_remove(struct platform_device *pdev) return 0; } +static void ftpm_plat_tee_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + ftpm_tee_remove(dev); +} + /** - * ftpm_tee_shutdown() - shutdown the TPM device + * ftpm_plat_tee_shutdown() - shutdown the TPM device * @pdev: the platform_device description. */ -static void ftpm_tee_shutdown(struct platform_device *pdev) +static void ftpm_plat_tee_shutdown(struct platform_device *pdev) { struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev); @@ -347,17 +315,60 @@ static const struct of_device_id of_ftpm_tee_ids[] = { }; MODULE_DEVICE_TABLE(of, of_ftpm_tee_ids); -static struct platform_driver ftpm_tee_driver = { +static struct platform_driver ftpm_tee_plat_driver = { .driver = { .name = "ftpm-tee", - .of_match_table = of_match_ptr(of_ftpm_tee_ids), + .of_match_table = of_ftpm_tee_ids, }, - .probe = ftpm_tee_probe, - .remove = ftpm_tee_remove, - .shutdown = ftpm_tee_shutdown, + .shutdown = ftpm_plat_tee_shutdown, + .probe = ftpm_plat_tee_probe, + .remove = ftpm_plat_tee_remove, }; -module_platform_driver(ftpm_tee_driver); +/* UUID of the fTPM TA */ +static const struct tee_client_device_id optee_ftpm_id_table[] = { + {UUID_INIT(0xbc50d971, 0xd4c9, 0x42c4, + 0x82, 0xcb, 0x34, 0x3f, 0xb7, 0xf3, 0x78, 0x96)}, + {} +}; + +MODULE_DEVICE_TABLE(tee, optee_ftpm_id_table); + +static struct tee_client_driver ftpm_tee_driver = { + .id_table = optee_ftpm_id_table, + .driver = { + .name = "optee-ftpm", + .bus = &tee_bus_type, + .probe = ftpm_tee_probe, + .remove = ftpm_tee_remove, + }, +}; + +static int __init ftpm_mod_init(void) +{ + int rc; + + rc = platform_driver_register(&ftpm_tee_plat_driver); + if (rc) + return rc; + + rc = driver_register(&ftpm_tee_driver.driver); + if (rc) { + platform_driver_unregister(&ftpm_tee_plat_driver); + return rc; + } + + return 0; +} + +static void __exit ftpm_mod_exit(void) +{ + platform_driver_unregister(&ftpm_tee_plat_driver); + driver_unregister(&ftpm_tee_driver.driver); +} + +module_init(ftpm_mod_init); +module_exit(ftpm_mod_exit); MODULE_AUTHOR("Thirupathaiah Annapureddy <thiruan@microsoft.com>"); MODULE_DESCRIPTION("TPM Driver for fTPM TA in TEE"); |
