drivers/tee/optee/device.c

Source file repositories/reference/linux-study-clean/drivers/tee/optee/device.c

File Facts

System
Linux kernel
Corpus path
drivers/tee/optee/device.c
Extension
.c
Size
4725 bytes
Lines
196
Domain
Driver Families
Bucket
drivers/tee
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019 Linaro Ltd.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/tee_core.h>
#include <linux/uuid.h>
#include "optee_private.h"

static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
	return (ver->impl_id == TEE_IMPL_ID_OPTEE);
}

static int get_devices(struct tee_context *ctx, u32 session,
		       struct tee_shm *device_shm, u32 *shm_size,
		       u32 func)
{
	int ret = 0;
	struct tee_ioctl_invoke_arg inv_arg;
	struct tee_param param[4];

	memset(&inv_arg, 0, sizeof(inv_arg));
	memset(&param, 0, sizeof(param));

	inv_arg.func = func;
	inv_arg.session = session;
	inv_arg.num_params = 4;

	/* Fill invoke cmd params */
	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
	param[0].u.memref.shm = device_shm;
	param[0].u.memref.size = *shm_size;
	param[0].u.memref.shm_offs = 0;

	ret = tee_client_invoke_func(ctx, &inv_arg, param);
	if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
			  (inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
		/*
		 * TEE_ERROR_STORAGE_NOT_AVAILABLE is returned when getting
		 * the list of device TAs that depends on RPMB but a usable
		 * RPMB device isn't found.
		 */
		if (inv_arg.ret == TEE_ERROR_STORAGE_NOT_AVAILABLE)
			return -ENODEV;
		pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
		       inv_arg.ret);
		return -EINVAL;
	}

	*shm_size = param[0].u.memref.size;

	return 0;
}

static void optee_release_device(struct device *dev)
{
	struct tee_client_device *optee_device = to_tee_client_device(dev);

	kfree(optee_device);
}

static ssize_t need_supplicant_show(struct device *dev,
				    struct device_attribute *attr,
				    char *buf)
{
	return 0;
}

static DEVICE_ATTR_RO(need_supplicant);

static int optee_register_device(const uuid_t *device_uuid, u32 func)
{
	struct tee_client_device *optee_device = NULL;
	int rc;

	optee_device = kzalloc_obj(*optee_device);
	if (!optee_device)
		return -ENOMEM;

	optee_device->dev.bus = &tee_bus_type;
	optee_device->dev.release = optee_release_device;
	if (dev_set_name(&optee_device->dev, "optee-ta-%pUb", device_uuid)) {
		kfree(optee_device);
		return -ENOMEM;
	}

Annotation

Implementation Notes