Received: by 2002:a89:288:0:b0:1f7:eeee:6653 with SMTP id j8csp391054lqh; Tue, 7 May 2024 02:17:28 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWH2H0YDgRIKbVPFfuuIVetPHP7epxzCPRcIANjOKJ5gO08UGEx/PsDvYjfsavnqJ4C5cjWlLY43ADw75NHV2O4uO29FWJpUoXlOau+ew== X-Google-Smtp-Source: AGHT+IH8THkcqtdO2JEZaWYNbGhCMRgKzr3KyqBgTAANKP+HulAdWMRuHxwKNsLUX2VbCpkL7HmY X-Received: by 2002:a05:6a00:8c4:b0:6f0:c828:65c1 with SMTP id s4-20020a056a0008c400b006f0c82865c1mr15711050pfu.2.1715073448544; Tue, 07 May 2024 02:17:28 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715073448; cv=pass; d=google.com; s=arc-20160816; b=tKPzoTOHrANqGfWXrT50N11H2EFqpcZvEykzQ3hpBVKr7s0pZ7Z18woMxhuHKt6Ojo ynn6Umkm1Mz8HTTJyt2VgZj42sWv825F7PuNZOj1KcQRerV7LFhhpUG9Cqoky87XDdHP jziUxL5UWaaGJHbYsPe2vKCq5DEcX6J4LAwu4fpwAvgxTxrlgopniuAN1uAPZPb9U87K WAbeQT4gO5i+22FFCxTdqgxC+q+/Bd4w+apUk5PshI8krSQImeaO1uLd5IQ2q/F0KhWs fq/D5FURqiKbwI3nB3Xwhk7CoQPIOj6HNVHLopmhiANAJAMQYF/JPGtDrkPG0FOrDtMH QyKA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=mV0VIqlFGT+bD5yp89WOjzq8GoGDkFtsoCocQ6f4NEo=; fh=RlDY2mPKy+HlQ1FzhBaZNhQbzI0xSu49jPq+8ZnZKCc=; b=oNAw6yahL/bqJ++0zwzYc1sPGCVE7tVQAPJWIdjZZ+1ByZefKc9PMD8U59eFEfPZW0 4xCRzQjMGAIn1vFm4EGtsZNBDBIPjZND3SJIqEVihpYBUD/03f7PGRPfHeWuj+A7VKVK jFZ55Fe61ccI6dUt2jQD2KIkCGDoCp83roo4nMHTnYwGrOxpu0DJNkWHV2NTw/Eo/6vu 1QX+MGDCPTcGEhrwEcy5Ql9Cm8bQkog5lCunKL5VfS3QIYZFCbFlXKeSJFg3fHEvSxx8 4fmHI97cMlciaArIxvv5cPNHjehaOwO6SHZmmtcaSoJk1B2HO7FD7mfMvnDIAhKB6l+6 o7Gg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ozGkwuNr; arc=pass (i=1 spf=pass spfdomain=linaro.org dkim=pass dkdomain=linaro.org dmarc=pass fromdomain=linaro.org); spf=pass (google.com: domain of linux-kernel+bounces-170924-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-170924-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id b9-20020a056a000cc900b006f47b111bdasi3978004pfv.377.2024.05.07.02.17.27 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 May 2024 02:17:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-170924-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ozGkwuNr; arc=pass (i=1 spf=pass spfdomain=linaro.org dkim=pass dkdomain=linaro.org dmarc=pass fromdomain=linaro.org); spf=pass (google.com: domain of linux-kernel+bounces-170924-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-170924-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 3E7C1B224C4 for ; Tue, 7 May 2024 09:17:27 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E60DB14E2F5; Tue, 7 May 2024 09:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="ozGkwuNr" Received: from mail-ej1-f50.google.com (mail-ej1-f50.google.com [209.85.218.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A85814E2C1 for ; Tue, 7 May 2024 09:16:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.50 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715073415; cv=none; b=TdNtej2k5SMJiY4cO1J6RgoEZlu5Kpxyz6rXXoxJB/RBjCchyU67tp8n2gJTegbo9/eO3wTSjwBo/T/4V28clJYmLC8Sev9wVexNQ+EOybFPRw0WZVAhoZNptDS5DlIelDQ5AK3LEbHpNn5RGfLeLMKSo4MxqmpiQfM5jEZLTS0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715073415; c=relaxed/simple; bh=N0TuA2i2xPrFjR3knug2kFSY7tYlNbNojWTX/exPHDA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=T6WnMGB+z7eN2XC1694j7Xt6luZxW9wW+RqKW4cSMa6TJaBoT3k4AbrmozO06e4jqk+V0XxZQnSk+/OZZcTURnWaHwOMMLHGAwYg/DTsJu1VW0e2eNpJsT+7k5mx91vAcDY6hyCE+r056foFWq9CwftRf2OGDUNekO24wMutncg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=ozGkwuNr; arc=none smtp.client-ip=209.85.218.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Received: by mail-ej1-f50.google.com with SMTP id a640c23a62f3a-a599a298990so766030666b.2 for ; Tue, 07 May 2024 02:16:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1715073411; x=1715678211; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mV0VIqlFGT+bD5yp89WOjzq8GoGDkFtsoCocQ6f4NEo=; b=ozGkwuNrS85RaG77NgomxPU1yIaAceLeHSk2q8jTwIbcUdHyDz/pAnsd4WTTm6Svim 2LTdIckCxhzoBYZWkNtYlrmXlSccluKp0xi35imVNy9DXNkm74l4xNY1DWd01MDi3q0r YFK+0TNdL6+WyQ+ZYC772ZLt7gs9tLQyVSqkvdb9zEWfY9YWxNmjPu6ifBWD7sUWjOmW LZpaqqCYOrII4xbAcuUpqn6tbp2r82OfhiQHDXlpKaB90scgEEbubqlJ4KsyuHvVnePl 632tOzZcywQd6Z/u0Ahvaw3TPpfLrh2/baNX/OF5QUDRh+wK6e19hAssHDLYUTOG7SZT C+OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715073411; x=1715678211; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mV0VIqlFGT+bD5yp89WOjzq8GoGDkFtsoCocQ6f4NEo=; b=Z0qi17gZ1eWdneT4lucRbCAc6ac8UfbKvKj92qVqXKITE+1K9Hnk1zGHMsQH40qsCF I/Lm7ht1m7+K59g6iTms2YCAAmYiTwv5tYDy8vMYQ2/h07n1JS23QHZwceOjen+MQ3ro hkIjhwteqJkmICl2QUHqTFwfHX5S84BAAzXmk5lRVs2Zc8yr3b6lEso1OafEIE4J2Z/P k1QJS+L+QeZBzygYnuo+dODGud+t5f2JNw/zjXXzTk1c46jfJlK+jk8U8s+RHJCaubUU 2zwxplJtt7hU/evItV1uUX+YpDaLCv596XtoP8XBNpHLz8k+a7StcWYJGe0Ybr/cjMyn bGag== X-Gm-Message-State: AOJu0YwIHo6qMsKc4zSiVyIxZ0b0yLD628mxym1G09AQCO2s/ipEs6Pt 6potTNOifpOaQT5eOuTA6oJAQSPHmtyRT7faDYLy4QjHBZdOr+8WEHkmJ7jT6K+xPDu9SZysYct b X-Received: by 2002:a17:906:3446:b0:a59:c52b:993d with SMTP id d6-20020a170906344600b00a59c52b993dmr3808409ejb.20.1715073410753; Tue, 07 May 2024 02:16:50 -0700 (PDT) Received: from rayden.urgonet (h-217-31-164-171.A175.priv.bahnhof.se. [217.31.164.171]) by smtp.gmail.com with ESMTPSA id o7-20020a1709061d4700b00a59a93a3ef4sm3976134ejh.149.2024.05.07.02.16.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 May 2024 02:16:49 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org, op-tee@lists.trustedfirmware.org Cc: Shyam Saini , Ulf Hansson , Linus Walleij , Jerome Forissier , Sumit Garg , Ilias Apalodimas , Bart Van Assche , Randy Dunlap , Ard Biesheuvel , Arnd Bergmann , Greg Kroah-Hartman , Manuel Traut , Jens Wiklander Subject: [PATCH v6 3/3] optee: probe RPMB device using RPMB subsystem Date: Tue, 7 May 2024 11:16:19 +0200 Message-Id: <20240507091619.2208810-4-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240507091619.2208810-1-jens.wiklander@linaro.org> References: <20240507091619.2208810-1-jens.wiklander@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Adds support in the OP-TEE drivers (both SMC and FF-A ABIs) to probe and use an RPMB device via the RPMB subsystem instead of passing the RPMB frames via tee-supplicant in user space. A fallback mechanism is kept to route RPMB frames via tee-supplicant if the RPMB subsystem isn't available. The OP-TEE RPC ABI is extended to support iterating over all RPMB devices until one is found with the expected RPMB key already programmed. Signed-off-by: Jens Wiklander --- drivers/tee/optee/core.c | 30 ++++++ drivers/tee/optee/device.c | 7 ++ drivers/tee/optee/ffa_abi.c | 8 ++ drivers/tee/optee/optee_private.h | 21 +++- drivers/tee/optee/optee_rpc_cmd.h | 35 +++++++ drivers/tee/optee/rpc.c | 166 ++++++++++++++++++++++++++++++ drivers/tee/optee/smc_abi.c | 7 ++ 7 files changed, 273 insertions(+), 1 deletion(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 3aed554bc8d8..082691c10a90 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,31 @@ void optee_pool_op_free_helper(struct tee_shm_pool *pool, struct tee_shm *shm, shm->pages = NULL; } +void optee_bus_scan_rpmb(struct work_struct *work) +{ + struct optee *optee = container_of(work, struct optee, + rpmb_scan_bus_work); + int ret; + + if (!optee->rpmb_scan_bus_done) { + ret = optee_enumerate_devices(PTA_CMD_GET_DEVICES_RPMB); + optee->rpmb_scan_bus_done = !ret; + if (ret && ret != -ENODEV) + pr_info("Scanning for RPMB device: ret %d\n", ret); + } +} + +int optee_rpmb_intf_rdev(struct notifier_block *intf, unsigned long action, + void *data) +{ + struct optee *optee = container_of(intf, struct optee, rpmb_intf); + + if (action == RPMB_NOTIFY_ADD_DEVICE) + schedule_work(&optee->rpmb_scan_bus_work); + + return 0; +} + static void optee_bus_scan(struct work_struct *work) { WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP)); @@ -161,6 +187,8 @@ void optee_release_supp(struct tee_context *ctx) void optee_remove_common(struct optee *optee) { + rpmb_interface_unregister(&optee->rpmb_intf); + cancel_work_sync(&optee->rpmb_scan_bus_work); /* Unregister OP-TEE specific client devices on TEE bus */ optee_unregister_devices(); @@ -177,6 +205,8 @@ void optee_remove_common(struct optee *optee) tee_shm_pool_free(optee->pool); optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); + rpmb_dev_put(optee->rpmb_dev); + mutex_destroy(&optee->rpmb_dev_mutex); } static int smc_abi_rc; diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c index 4b1092127694..4274876857c8 100644 --- a/drivers/tee/optee/device.c +++ b/drivers/tee/optee/device.c @@ -43,6 +43,13 @@ static int get_devices(struct tee_context *ctx, u32 session, 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; diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c index ecb5eb079408..a8dfdb30b4e8 100644 --- a/drivers/tee/optee/ffa_abi.c +++ b/drivers/tee/optee/ffa_abi.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -934,6 +935,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) optee_cq_init(&optee->call_queue, 0); optee_supp_init(&optee->supp); optee_shm_arg_cache_init(optee, arg_cache_flags); + mutex_init(&optee->rpmb_dev_mutex); ffa_dev_set_drvdata(ffa_dev, optee); ctx = teedev_open(optee->teedev); if (IS_ERR(ctx)) { @@ -955,6 +957,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) if (rc) goto err_unregister_devices; + INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb); + optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev; + rpmb_interface_register(&optee->rpmb_intf); pr_info("initialized driver\n"); return 0; @@ -968,6 +973,9 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev) teedev_close_context(ctx); err_rhashtable_free: rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL); + rpmb_dev_put(optee->rpmb_dev); + mutex_destroy(&optee->rpmb_dev_mutex); + rpmb_interface_unregister(&optee->rpmb_intf); optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); mutex_destroy(&optee->ffa.mutex); diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h index 7a5243c78b55..ae72f3dda1d2 100644 --- a/drivers/tee/optee/optee_private.h +++ b/drivers/tee/optee/optee_private.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -20,11 +21,13 @@ /* Some Global Platform error codes used in this driver */ #define TEEC_SUCCESS 0x00000000 #define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008 #define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A #define TEEC_ERROR_COMMUNICATION 0xFFFF000E #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C #define TEEC_ERROR_BUSY 0xFFFF000D #define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 +#define TEE_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003 #define TEEC_ORIGIN_COMMS 0x00000002 @@ -197,6 +200,12 @@ struct optee_ops { * @notif: notification synchronization struct * @supp: supplicant synchronization struct for RPC to supplicant * @pool: shared memory pool + * @mutex: mutex protecting @rpmb_dev + * @rpmb_dev: current RPMB device or NULL + * @rpmb_scan_bus_done flag if device registation of RPMB dependent devices + * was already done + * @rpmb_scan_bus_work workq to for an RPMB device and to scan optee bus + * and register RPMB dependent optee drivers * @rpc_param_count: If > 0 number of RPC parameters to make room for * @scan_bus_done flag if device registation was already done. * @scan_bus_work workq to scan optee bus and register optee drivers @@ -215,9 +224,15 @@ struct optee { struct optee_notif notif; struct optee_supp supp; struct tee_shm_pool *pool; + /* Protects rpmb_dev pointer */ + struct mutex rpmb_dev_mutex; + struct rpmb_dev *rpmb_dev; + struct notifier_block rpmb_intf; unsigned int rpc_param_count; - bool scan_bus_done; + bool scan_bus_done; + bool rpmb_scan_bus_done; struct work_struct scan_bus_work; + struct work_struct rpmb_scan_bus_work; }; struct optee_session { @@ -280,8 +295,12 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session); #define PTA_CMD_GET_DEVICES 0x0 #define PTA_CMD_GET_DEVICES_SUPP 0x1 +#define PTA_CMD_GET_DEVICES_RPMB 0x2 int optee_enumerate_devices(u32 func); void optee_unregister_devices(void); +void optee_bus_scan_rpmb(struct work_struct *work); +int optee_rpmb_intf_rdev(struct notifier_block *intf, unsigned long action, + void *data); int optee_pool_op_alloc_helper(struct tee_shm_pool *pool, struct tee_shm *shm, size_t size, size_t align, diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h index f3f06e0994a7..4a3c02914f9c 100644 --- a/drivers/tee/optee/optee_rpc_cmd.h +++ b/drivers/tee/optee/optee_rpc_cmd.h @@ -103,4 +103,39 @@ /* I2C master control flags */ #define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0) +/* + * Reset RPMB probing + * + * Releases an eventually already used RPMB devices and starts over searching + * for RPMB devices. Returns the kind of shared memory to use in subsequent + * OPTEE_RPC_CMD_RPMB_PROBE_NEXT and OPTEE_RPC_CMD_RPMB calls. + * + * [out] value[0].a OPTEE_RPC_SHM_TYPE_*, the parameter for + * OPTEE_RPC_CMD_SHM_ALLOC + */ +#define OPTEE_RPC_CMD_RPMB_PROBE_RESET 22 + +/* + * Probe next RPMB device + * + * [out] value[0].a Type of RPMB device, OPTEE_RPC_RPMB_* + * [out] value[0].b EXT CSD-slice 168 "RPMB Size" + * [out] value[0].c EXT CSD-slice 222 "Reliable Write Sector Count" + * [out] memref[1] Buffer with the raw CID + */ +#define OPTEE_RPC_CMD_RPMB_PROBE_NEXT 23 + +/* Type of RPMB device */ +#define OPTEE_RPC_RPMB_EMMC 0 +#define OPTEE_RPC_RPMB_UFS 1 +#define OPTEE_RPC_RPMB_NVME 2 + +/* + * Replay Protected Memory Block access + * + * [in] memref[0] Frames to device + * [out] memref[1] Frames from device + */ +#define OPTEE_RPC_CMD_RPMB_FRAMES 24 + #endif /*__OPTEE_RPC_CMD_H*/ diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c index e69bc6380683..f3acb4240fcb 100644 --- a/drivers/tee/optee/rpc.c +++ b/drivers/tee/optee/rpc.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include "optee_private.h" @@ -255,6 +256,162 @@ void optee_rpc_cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm) optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, ¶m); } +static void handle_rpc_func_rpmb_probe_reset(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + struct tee_param params[1]; + + if (!IS_ENABLED(CONFIG_RPMB)) { + handle_rpc_supp_cmd(ctx, optee, arg); + return; + } + + if (arg->num_params != ARRAY_SIZE(params) || + optee->ops->from_msg_param(optee, params, arg->num_params, + arg->params) || + params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + params[0].u.value.a = OPTEE_RPC_SHM_TYPE_KERNEL; + params[0].u.value.b = 0; + params[0].u.value.c = 0; + if (optee->ops->to_msg_param(optee, arg->params, + arg->num_params, params)) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + mutex_lock(&optee->rpmb_dev_mutex); + rpmb_dev_put(optee->rpmb_dev); + optee->rpmb_dev = NULL; + mutex_unlock(&optee->rpmb_dev_mutex); + + arg->ret = TEEC_SUCCESS; +} + +static int rpmb_type_to_rpc_type(enum rpmb_type rtype) +{ + switch (rtype) { + case RPMB_TYPE_EMMC: + return OPTEE_RPC_RPMB_EMMC; + case RPMB_TYPE_UFS: + return OPTEE_RPC_RPMB_UFS; + case RPMB_TYPE_NVME: + return OPTEE_RPC_RPMB_NVME; + default: + return -1; + } +} + +static int rpc_rpmb_match(struct rpmb_dev *rdev, const void *data) +{ + return rpmb_type_to_rpc_type(rdev->descr.type) >= 0; +} + +static void handle_rpc_func_rpmb_probe_next(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + struct rpmb_dev *rdev; + struct tee_param params[2]; + void *buf; + + if (!IS_REACHABLE(CONFIG_RPMB)) { + handle_rpc_supp_cmd(ctx, optee, arg); + return; + } + + if (arg->num_params != ARRAY_SIZE(params) || + optee->ops->from_msg_param(optee, params, arg->num_params, + arg->params) || + params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT || + params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + buf = tee_shm_get_va(params[1].u.memref.shm, + params[1].u.memref.shm_offs); + if (!buf) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + mutex_lock(&optee->rpmb_dev_mutex); + rdev = rpmb_dev_find_device(NULL, optee->rpmb_dev, rpc_rpmb_match); + rpmb_dev_put(optee->rpmb_dev); + optee->rpmb_dev = rdev; + mutex_unlock(&optee->rpmb_dev_mutex); + + if (!rdev) { + arg->ret = TEEC_ERROR_ITEM_NOT_FOUND; + return; + } + + if (params[1].u.memref.size < rdev->descr.dev_id_len) { + arg->ret = TEEC_ERROR_SHORT_BUFFER; + return; + } + memcpy(buf, rdev->descr.dev_id, rdev->descr.dev_id_len); + params[1].u.memref.size = rdev->descr.dev_id_len; + params[0].u.value.a = rpmb_type_to_rpc_type(rdev->descr.type); + params[0].u.value.b = rdev->descr.capacity; + params[0].u.value.c = rdev->descr.reliable_wr_count; + if (optee->ops->to_msg_param(optee, arg->params, + arg->num_params, params)) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + return; + } + + arg->ret = TEEC_SUCCESS; +} + +static void handle_rpc_func_rpmb_frames(struct tee_context *ctx, + struct optee *optee, + struct optee_msg_arg *arg) +{ + struct tee_param params[2]; + struct rpmb_dev *rdev; + void *p0, *p1; + + mutex_lock(&optee->rpmb_dev_mutex); + rdev = rpmb_dev_get(optee->rpmb_dev); + mutex_unlock(&optee->rpmb_dev_mutex); + if (!rdev) { + handle_rpc_supp_cmd(ctx, optee, arg); + return; + } + + if (arg->num_params != ARRAY_SIZE(params) || + optee->ops->from_msg_param(optee, params, arg->num_params, + arg->params) || + params[0].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || + params[1].attr != TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + p0 = tee_shm_get_va(params[0].u.memref.shm, + params[0].u.memref.shm_offs); + p1 = tee_shm_get_va(params[1].u.memref.shm, + params[1].u.memref.shm_offs); + if (rpmb_route_frames(rdev, p0, params[0].u.memref.size, p1, + params[1].u.memref.size)) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + if (optee->ops->to_msg_param(optee, arg->params, + arg->num_params, params)) { + arg->ret = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + arg->ret = TEEC_SUCCESS; +out: + rpmb_dev_put(rdev); +} + void optee_rpc_cmd(struct tee_context *ctx, struct optee *optee, struct optee_msg_arg *arg) { @@ -271,6 +428,15 @@ void optee_rpc_cmd(struct tee_context *ctx, struct optee *optee, case OPTEE_RPC_CMD_I2C_TRANSFER: handle_rpc_func_cmd_i2c_transfer(ctx, arg); break; + case OPTEE_RPC_CMD_RPMB_PROBE_RESET: + handle_rpc_func_rpmb_probe_reset(ctx, optee, arg); + break; + case OPTEE_RPC_CMD_RPMB_PROBE_NEXT: + handle_rpc_func_rpmb_probe_next(ctx, optee, arg); + break; + case OPTEE_RPC_CMD_RPMB_FRAMES: + handle_rpc_func_rpmb_frames(ctx, optee, arg); + break; default: handle_rpc_supp_cmd(ctx, optee, arg); } diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index a37f87087e5c..c23bcf35c8cb 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1715,6 +1716,7 @@ static int optee_probe(struct platform_device *pdev) optee->smc.memremaped_shm = memremaped_shm; optee->pool = pool; optee_shm_arg_cache_init(optee, arg_cache_flags); + mutex_init(&optee->rpmb_dev_mutex); platform_set_drvdata(pdev, optee); ctx = teedev_open(optee->teedev); @@ -1769,6 +1771,9 @@ static int optee_probe(struct platform_device *pdev) if (rc) goto err_disable_shm_cache; + INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb); + optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev; + rpmb_interface_register(&optee->rpmb_intf); pr_info("initialized driver\n"); return 0; @@ -1782,6 +1787,8 @@ static int optee_probe(struct platform_device *pdev) err_close_ctx: teedev_close_context(ctx); err_supp_uninit: + rpmb_dev_put(optee->rpmb_dev); + mutex_destroy(&optee->rpmb_dev_mutex); optee_shm_arg_cache_uninit(optee); optee_supp_uninit(&optee->supp); mutex_destroy(&optee->call_queue.mutex); -- 2.34.1