Enable multi-stage OP-TEE bus enumeration
Probes drivers on the OP-TEE bus in two steps. First for drivers which do not depend on tee-supplicant. After tee-supplicant has been started probe the devices which do depend on tee-supplicant. Also introduces driver which uses an OP-TEE based fTPM Trusted Application depends on tee-supplicant NV RAM implementation based on RPMB secure storage. -----BEGIN PGP SIGNATURE----- iQJOBAABCgA4FiEEFV+gSSXZJY9ZyuB5LinzTIcAHJcFAl8IIS8aHGplbnMud2lr bGFuZGVyQGxpbmFyby5vcmcACgkQLinzTIcAHJfy4A//XAbKsdQo8ws3cRba++S5 VPdLIf0gdjC7LCPh8z4GD32EBzKAq0HJbgoX27cNGv3e9saN8q8vDOmnUlQb+eP5 ZoQUgb9OUY+I4IPV+CVl+4HcxUhiQSZe36x6yubGPk+fikzLy/W/LZm2RnQdw83W iLuKlAy+hbLdPVJBoFe/AGsy5SndyjoJ1/0GXRoN6RNk2GPNHhAYfmH6FxPwghL4 n0sqa4UjeI8t/x85l7Pwn0b/0vmXG65JQqaICHosfEoJR6JfGqFtaEJ3ibEyz90b QvuAFRlghPTYFwNOzBuoC958E4hQ2ulXXBL7soF4f9hRmqfv5u7L1C4ctcL6ZQtB 69XIkh9f9Og2ZG/UUgY7X1ZENk2XcAAiSsBqmF2dp170ron/+m7AYiYcPkMC9sSt G0ubdHtXah6fX+TCO9TW/JOm5xl/IrspMZF2jMaLtarZeiacUZSuGIuwrySdEtdn 49G2Xv2ZrPMjWsNyAgvR9myHYSlX7lioIJJ5oTURHDM/68i+KZCg/r88GJJjCYBY C1o0hILQ5o58L3atoa8JtPMs7cKF5S4UvbWl0otpVTUC9wcVyQOAPkrpTYplkKpy ByCGjxJ5W1OLpO8M1/US23DlMXGkqpX4eSvGUTtybqv0pr4FmEdKbgB1HNh9lA0/ ZjFOfDwn9qLRTzLVQ7DZTGI= =PDtV -----END PGP SIGNATURE----- Merge tag 'optee-bus-for-v5.9' of git://git.linaro.org/people/jens.wiklander/linux-tee into arm/drivers Enable multi-stage OP-TEE bus enumeration Probes drivers on the OP-TEE bus in two steps. First for drivers which do not depend on tee-supplicant. After tee-supplicant has been started probe the devices which do depend on tee-supplicant. Also introduces driver which uses an OP-TEE based fTPM Trusted Application depends on tee-supplicant NV RAM implementation based on RPMB secure storage. * tag 'optee-bus-for-v5.9' of git://git.linaro.org/people/jens.wiklander/linux-tee: tpm_ftpm_tee: register driver on TEE bus optee: enable support for multi-stage bus enumeration optee: use uuid for sysfs driver entry Link: https://lore.kernel.org/r/20200710085230.GA1312913@jade Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
38d9dff186
|
@ -0,0 +1,8 @@
|
||||||
|
What: /sys/bus/tee/devices/optee-ta-<uuid>/
|
||||||
|
Date: May 2020
|
||||||
|
KernelVersion 5.8
|
||||||
|
Contact: op-tee@lists.trustedfirmware.org
|
||||||
|
Description:
|
||||||
|
OP-TEE bus provides reference to registered drivers under this directory. The <uuid>
|
||||||
|
matches Trusted Application (TA) driver and corresponding TA in secure OS. Drivers
|
||||||
|
are free to create needed API under optee-ta-<uuid> directory.
|
|
@ -12697,6 +12697,7 @@ OP-TEE DRIVER
|
||||||
M: Jens Wiklander <jens.wiklander@linaro.org>
|
M: Jens Wiklander <jens.wiklander@linaro.org>
|
||||||
L: tee-dev@lists.linaro.org
|
L: tee-dev@lists.linaro.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
F: Documentation/ABI/testing/sysfs-bus-optee-devices
|
||||||
F: drivers/tee/optee/
|
F: drivers/tee/optee/
|
||||||
|
|
||||||
OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
|
OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER
|
||||||
|
|
|
@ -214,11 +214,10 @@ static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data)
|
||||||
* Return:
|
* Return:
|
||||||
* On success, 0. On failure, -errno.
|
* 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;
|
int rc;
|
||||||
struct tpm_chip *chip;
|
struct tpm_chip *chip;
|
||||||
struct device *dev = &pdev->dev;
|
|
||||||
struct ftpm_tee_private *pvt_data = NULL;
|
struct ftpm_tee_private *pvt_data = NULL;
|
||||||
struct tee_ioctl_open_session_arg sess_arg;
|
struct tee_ioctl_open_session_arg sess_arg;
|
||||||
|
|
||||||
|
@ -297,6 +296,13 @@ out_tee_session:
|
||||||
return rc;
|
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
|
* ftpm_tee_remove() - remove the TPM device
|
||||||
* @pdev: the platform_device description.
|
* @pdev: the platform_device description.
|
||||||
|
@ -304,9 +310,9 @@ out_tee_session:
|
||||||
* Return:
|
* Return:
|
||||||
* 0 always.
|
* 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 */
|
/* Release the chip */
|
||||||
tpm_chip_unregister(pvt_data->chip);
|
tpm_chip_unregister(pvt_data->chip);
|
||||||
|
@ -328,11 +334,18 @@ static int ftpm_tee_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ftpm_plat_tee_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
|
||||||
|
return ftpm_tee_remove(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ftpm_tee_shutdown() - shutdown the TPM device
|
* ftpm_tee_shutdown() - shutdown the TPM device
|
||||||
* @pdev: the platform_device description.
|
* @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);
|
struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
|
@ -347,17 +360,54 @@ static const struct of_device_id of_ftpm_tee_ids[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, 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 = {
|
.driver = {
|
||||||
.name = "ftpm-tee",
|
.name = "ftpm-tee",
|
||||||
.of_match_table = of_match_ptr(of_ftpm_tee_ids),
|
.of_match_table = of_match_ptr(of_ftpm_tee_ids),
|
||||||
},
|
},
|
||||||
.probe = ftpm_tee_probe,
|
.shutdown = ftpm_plat_tee_shutdown,
|
||||||
.remove = ftpm_tee_remove,
|
.probe = ftpm_plat_tee_probe,
|
||||||
.shutdown = ftpm_tee_shutdown,
|
.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;
|
||||||
|
|
||||||
|
return driver_register(&ftpm_tee_driver.driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_AUTHOR("Thirupathaiah Annapureddy <thiruan@microsoft.com>");
|
||||||
MODULE_DESCRIPTION("TPM Driver for fTPM TA in TEE");
|
MODULE_DESCRIPTION("TPM Driver for fTPM TA in TEE");
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/tee_drv.h>
|
#include <linux/tee_drv.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
#include "optee_private.h"
|
#include "optee_private.h"
|
||||||
#include "optee_smc.h"
|
#include "optee_smc.h"
|
||||||
#include "shm_pool.h"
|
#include "shm_pool.h"
|
||||||
|
@ -218,6 +219,11 @@ static void optee_get_version(struct tee_device *teedev,
|
||||||
*vers = v;
|
*vers = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void optee_bus_scan(struct work_struct *work)
|
||||||
|
{
|
||||||
|
WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));
|
||||||
|
}
|
||||||
|
|
||||||
static int optee_open(struct tee_context *ctx)
|
static int optee_open(struct tee_context *ctx)
|
||||||
{
|
{
|
||||||
struct optee_context_data *ctxdata;
|
struct optee_context_data *ctxdata;
|
||||||
|
@ -241,8 +247,18 @@ static int optee_open(struct tee_context *ctx)
|
||||||
kfree(ctxdata);
|
kfree(ctxdata);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!optee->scan_bus_done) {
|
||||||
|
INIT_WORK(&optee->scan_bus_work, optee_bus_scan);
|
||||||
|
optee->scan_bus_wq = create_workqueue("optee_bus_scan");
|
||||||
|
if (!optee->scan_bus_wq) {
|
||||||
|
kfree(ctxdata);
|
||||||
|
return -ECHILD;
|
||||||
|
}
|
||||||
|
queue_work(optee->scan_bus_wq, &optee->scan_bus_work);
|
||||||
|
optee->scan_bus_done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
mutex_init(&ctxdata->mutex);
|
mutex_init(&ctxdata->mutex);
|
||||||
INIT_LIST_HEAD(&ctxdata->sess_list);
|
INIT_LIST_HEAD(&ctxdata->sess_list);
|
||||||
|
|
||||||
|
@ -296,8 +312,13 @@ static void optee_release(struct tee_context *ctx)
|
||||||
|
|
||||||
ctx->data = NULL;
|
ctx->data = NULL;
|
||||||
|
|
||||||
if (teedev == optee->supp_teedev)
|
if (teedev == optee->supp_teedev) {
|
||||||
|
if (optee->scan_bus_wq) {
|
||||||
|
destroy_workqueue(optee->scan_bus_wq);
|
||||||
|
optee->scan_bus_wq = NULL;
|
||||||
|
}
|
||||||
optee_supp_release(&optee->supp);
|
optee_supp_release(&optee->supp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct tee_driver_ops optee_ops = {
|
static const struct tee_driver_ops optee_ops = {
|
||||||
|
@ -675,7 +696,7 @@ static int optee_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, optee);
|
platform_set_drvdata(pdev, optee);
|
||||||
|
|
||||||
rc = optee_enumerate_devices();
|
rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
optee_remove(pdev);
|
optee_remove(pdev);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -11,18 +11,6 @@
|
||||||
#include <linux/uuid.h>
|
#include <linux/uuid.h>
|
||||||
#include "optee_private.h"
|
#include "optee_private.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Get device UUIDs
|
|
||||||
*
|
|
||||||
* [out] memref[0] Array of device UUIDs
|
|
||||||
*
|
|
||||||
* Return codes:
|
|
||||||
* TEE_SUCCESS - Invoke command success
|
|
||||||
* TEE_ERROR_BAD_PARAMETERS - Incorrect input param
|
|
||||||
* TEE_ERROR_SHORT_BUFFER - Output buffer size less than required
|
|
||||||
*/
|
|
||||||
#define PTA_CMD_GET_DEVICES 0x0
|
|
||||||
|
|
||||||
static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
|
static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
|
||||||
{
|
{
|
||||||
if (ver->impl_id == TEE_IMPL_ID_OPTEE)
|
if (ver->impl_id == TEE_IMPL_ID_OPTEE)
|
||||||
|
@ -32,7 +20,8 @@ static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_devices(struct tee_context *ctx, u32 session,
|
static int get_devices(struct tee_context *ctx, u32 session,
|
||||||
struct tee_shm *device_shm, u32 *shm_size)
|
struct tee_shm *device_shm, u32 *shm_size,
|
||||||
|
u32 func)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct tee_ioctl_invoke_arg inv_arg;
|
struct tee_ioctl_invoke_arg inv_arg;
|
||||||
|
@ -41,8 +30,7 @@ static int get_devices(struct tee_context *ctx, u32 session,
|
||||||
memset(&inv_arg, 0, sizeof(inv_arg));
|
memset(&inv_arg, 0, sizeof(inv_arg));
|
||||||
memset(¶m, 0, sizeof(param));
|
memset(¶m, 0, sizeof(param));
|
||||||
|
|
||||||
/* Invoke PTA_CMD_GET_DEVICES function */
|
inv_arg.func = func;
|
||||||
inv_arg.func = PTA_CMD_GET_DEVICES;
|
|
||||||
inv_arg.session = session;
|
inv_arg.session = session;
|
||||||
inv_arg.num_params = 4;
|
inv_arg.num_params = 4;
|
||||||
|
|
||||||
|
@ -65,7 +53,7 @@ static int get_devices(struct tee_context *ctx, u32 session,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int optee_register_device(const uuid_t *device_uuid, u32 device_id)
|
static int optee_register_device(const uuid_t *device_uuid)
|
||||||
{
|
{
|
||||||
struct tee_client_device *optee_device = NULL;
|
struct tee_client_device *optee_device = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -75,7 +63,10 @@ static int optee_register_device(const uuid_t *device_uuid, u32 device_id)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
optee_device->dev.bus = &tee_bus_type;
|
optee_device->dev.bus = &tee_bus_type;
|
||||||
dev_set_name(&optee_device->dev, "optee-clnt%u", device_id);
|
if (dev_set_name(&optee_device->dev, "optee-ta-%pUb", device_uuid)) {
|
||||||
|
kfree(optee_device);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
uuid_copy(&optee_device->id.uuid, device_uuid);
|
uuid_copy(&optee_device->id.uuid, device_uuid);
|
||||||
|
|
||||||
rc = device_register(&optee_device->dev);
|
rc = device_register(&optee_device->dev);
|
||||||
|
@ -87,7 +78,7 @@ static int optee_register_device(const uuid_t *device_uuid, u32 device_id)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int optee_enumerate_devices(void)
|
static int __optee_enumerate_devices(u32 func)
|
||||||
{
|
{
|
||||||
const uuid_t pta_uuid =
|
const uuid_t pta_uuid =
|
||||||
UUID_INIT(0x7011a688, 0xddde, 0x4053,
|
UUID_INIT(0x7011a688, 0xddde, 0x4053,
|
||||||
|
@ -118,7 +109,7 @@ int optee_enumerate_devices(void)
|
||||||
goto out_ctx;
|
goto out_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = get_devices(ctx, sess_arg.session, NULL, &shm_size);
|
rc = get_devices(ctx, sess_arg.session, NULL, &shm_size, func);
|
||||||
if (rc < 0 || !shm_size)
|
if (rc < 0 || !shm_size)
|
||||||
goto out_sess;
|
goto out_sess;
|
||||||
|
|
||||||
|
@ -130,7 +121,7 @@ int optee_enumerate_devices(void)
|
||||||
goto out_sess;
|
goto out_sess;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size);
|
rc = get_devices(ctx, sess_arg.session, device_shm, &shm_size, func);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out_shm;
|
goto out_shm;
|
||||||
|
|
||||||
|
@ -144,7 +135,7 @@ int optee_enumerate_devices(void)
|
||||||
num_devices = shm_size / sizeof(uuid_t);
|
num_devices = shm_size / sizeof(uuid_t);
|
||||||
|
|
||||||
for (idx = 0; idx < num_devices; idx++) {
|
for (idx = 0; idx < num_devices; idx++) {
|
||||||
rc = optee_register_device(&device_uuid[idx], idx);
|
rc = optee_register_device(&device_uuid[idx]);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_shm;
|
goto out_shm;
|
||||||
}
|
}
|
||||||
|
@ -158,3 +149,8 @@ out_ctx:
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int optee_enumerate_devices(u32 func)
|
||||||
|
{
|
||||||
|
return __optee_enumerate_devices(func);
|
||||||
|
}
|
||||||
|
|
|
@ -78,6 +78,9 @@ struct optee_supp {
|
||||||
* @memremaped_shm virtual address of memory in shared memory pool
|
* @memremaped_shm virtual address of memory in shared memory pool
|
||||||
* @sec_caps: secure world capabilities defined by
|
* @sec_caps: secure world capabilities defined by
|
||||||
* OPTEE_SMC_SEC_CAP_* in optee_smc.h
|
* OPTEE_SMC_SEC_CAP_* in optee_smc.h
|
||||||
|
* @scan_bus_done flag if device registation was already done.
|
||||||
|
* @scan_bus_wq workqueue to scan optee bus and register optee drivers
|
||||||
|
* @scan_bus_work workq to scan optee bus and register optee drivers
|
||||||
*/
|
*/
|
||||||
struct optee {
|
struct optee {
|
||||||
struct tee_device *supp_teedev;
|
struct tee_device *supp_teedev;
|
||||||
|
@ -89,6 +92,9 @@ struct optee {
|
||||||
struct tee_shm_pool *pool;
|
struct tee_shm_pool *pool;
|
||||||
void *memremaped_shm;
|
void *memremaped_shm;
|
||||||
u32 sec_caps;
|
u32 sec_caps;
|
||||||
|
bool scan_bus_done;
|
||||||
|
struct workqueue_struct *scan_bus_wq;
|
||||||
|
struct work_struct scan_bus_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct optee_session {
|
struct optee_session {
|
||||||
|
@ -173,7 +179,9 @@ void optee_free_pages_list(void *array, size_t num_entries);
|
||||||
void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
|
void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
|
||||||
size_t page_offset);
|
size_t page_offset);
|
||||||
|
|
||||||
int optee_enumerate_devices(void);
|
#define PTA_CMD_GET_DEVICES 0x0
|
||||||
|
#define PTA_CMD_GET_DEVICES_SUPP 0x1
|
||||||
|
int optee_enumerate_devices(u32 func);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Small helpers
|
* Small helpers
|
||||||
|
|
Loading…
Reference in New Issue