All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 00/10] AVB using OP-TEE
@ 2018-08-13 15:53 Jens Wiklander
  2018-08-13 15:53 ` [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too Jens Wiklander
                   ` (10 more replies)
  0 siblings, 11 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Hi,

This adds support for storing AVB rollback indexes in the RPMB partition.
The RPMB partition (content and key) is managed by OP-TEE
(https://www.op-tee.org/) which is a secure OS leveraging ARM TrustZone.

The Linux kernel can already support OP-TEE with reading and updating
rollback indexes in the RPMB partition, the catch is that this is needed
before the kernel has booted.

The design here is the same as what is in the Linux kernel, with the
exception that the user space daemon tee-supplicant is integrated in the
OP-TEE driver here (drivers/tee/optee/supplicant.c) instead. A new uclass
(UCLASS_TEE) is introduced to provide an abstraction for interfacing with a
Trusted Execution Environment (TEE). There's also the OP-TEE driver using
UCLASS_TEE for registration.

A Trusted Application (TA) interface is added to be used by the AVB verify
functions which are updated accordingly. The TA is managed by OP-TEE and is
executed in a secure TrustZone protected environment.

The header files drivers/tee/optee/optee_{msg,msg_supplicant,smc}.h and
include/tee/optee_ta_avb.h are copied from
https://github.com/OP-TEE/optee_os/tree/master more or less unmodified.
They may need to be updated from time to time in order to support new
features.

In MMC there's a new function, mmc_rpmb_route_frames(), which as the name
suggests is used to route RPMB frames to/from the MMC. This saves OP-TEE
from implementing an MMC driver which would need to share resources with
its counterpart here in U-boot.

This was tested on a Hikey (Kirin 620) board.

I've added myself as maintainer of the TEE stuff.

Thanks,
Jens

Jens Wiklander (10):
  dm: fdt: scan for devices under /firmware too
  cmd: avb read_rb: print rb_idx in hexadecimal
  mmc: rpmb: add mmc_rpmb_route_frames()
  Add UCLASS_TEE for Trusted Execution Environment
  dt/bindings: add bindings for optee
  tee: add OP-TEE driver
  arm: dt: hikey: Add optee node
  optee: support routing of rpmb data frames to mmc
  tee: optee: support AVB trusted application
  avb_verify: support using OP-TEE TA AVB

 MAINTAINERS                                   |   7 +
 arch/arm/dts/hi6220-hikey.dts                 |   7 +
 cmd/avb.c                                     |   2 +-
 common/avb_verify.c                           | 132 +++-
 .../firmware/linaro,optee-tz.txt              |  31 +
 drivers/Kconfig                               |   2 +
 drivers/Makefile                              |   1 +
 drivers/core/root.c                           |  15 +-
 drivers/mmc/rpmb.c                            | 160 +++++
 drivers/tee/Kconfig                           |  18 +
 drivers/tee/Makefile                          |   4 +
 drivers/tee/optee/Kconfig                     |  23 +
 drivers/tee/optee/Makefile                    |   5 +
 drivers/tee/optee/core.c                      | 622 ++++++++++++++++++
 drivers/tee/optee/optee_msg.h                 | 423 ++++++++++++
 drivers/tee/optee/optee_msg_supplicant.h      | 234 +++++++
 drivers/tee/optee/optee_private.h             |  41 ++
 drivers/tee/optee/optee_smc.h                 | 444 +++++++++++++
 drivers/tee/optee/rpmb.c                      | 184 ++++++
 drivers/tee/optee/supplicant.c                |  92 +++
 drivers/tee/tee-uclass.c                      | 180 +++++
 include/avb_verify.h                          |   4 +
 include/dm/uclass-id.h                        |   1 +
 include/mmc.h                                 |   2 +
 include/tee.h                                 | 141 ++++
 include/tee/optee_ta_avb.h                    |  48 ++
 26 files changed, 2816 insertions(+), 7 deletions(-)
 create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt
 create mode 100644 drivers/tee/Kconfig
 create mode 100644 drivers/tee/Makefile
 create mode 100644 drivers/tee/optee/Kconfig
 create mode 100644 drivers/tee/optee/Makefile
 create mode 100644 drivers/tee/optee/core.c
 create mode 100644 drivers/tee/optee/optee_msg.h
 create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
 create mode 100644 drivers/tee/optee/optee_private.h
 create mode 100644 drivers/tee/optee/optee_smc.h
 create mode 100644 drivers/tee/optee/rpmb.c
 create mode 100644 drivers/tee/optee/supplicant.c
 create mode 100644 drivers/tee/tee-uclass.c
 create mode 100644 include/tee.h
 create mode 100644 include/tee/optee_ta_avb.h

-- 
2.17.1

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-15 14:17   ` Tom Rini
  2018-08-13 15:53 ` [U-Boot] [PATCH 02/10] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Just as /chosen may contain devices /firmware may contain devices, scan
for devices under /firmware too.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 drivers/core/root.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/core/root.c b/drivers/core/root.c
index 72bcc7d7f2a3..0dca507e1187 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
 	for (offset = fdt_first_subnode(blob, offset);
 	     offset > 0;
 	     offset = fdt_next_subnode(blob, offset)) {
-		/* "chosen" node isn't a device itself but may contain some: */
-		if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
-			pr_debug("parsing subnodes of \"chosen\"\n");
+		const char *node_name = fdt_get_name(blob, offset, NULL);
+
+		/*
+		 * The "chosen" and "firmware" nodes aren't devices
+		 * themselves but may contain some:
+		 */
+		if (!strcmp(node_name, "chosen") ||
+		    !strcmp(node_name, "firmware")) {
+			pr_debug("parsing subnodes of \"%s\"\n", node_name);
 
 			err = dm_scan_fdt_node(parent, blob, offset,
 					       pre_reloc_only);
@@ -286,8 +292,7 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
 		err = lists_bind_fdt(parent, offset_to_ofnode(offset), NULL);
 		if (err && !ret) {
 			ret = err;
-			debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
-			      ret);
+			debug("%s: ret=%d\n", node_name, ret);
 		}
 	}
 
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 02/10] cmd: avb read_rb: print rb_idx in hexadecimal
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
  2018-08-13 15:53 ` [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-14 11:34   ` Igor Opaniuk
  2018-08-13 15:53 ` [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Prior to this patch was do_avb_write_rb() reading supplied rb_idx as a
hexadecimal number while do_avb_read_rb() printed the read out rb_idx as
decimal number. For consistency change do_avb_read_rb() to print rb_idx
as a hexadeciaml number too.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 cmd/avb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/avb.c b/cmd/avb.c
index f045a0c64c4a..ca4b26d5d7b3 100644
--- a/cmd/avb.c
+++ b/cmd/avb.c
@@ -158,7 +158,7 @@ int do_avb_read_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
 	    AVB_IO_RESULT_OK) {
-		printf("Rollback index: %llu\n", rb_idx);
+		printf("Rollback index: %llx\n", rb_idx);
 		return CMD_RET_SUCCESS;
 	}
 	return CMD_RET_FAILURE;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
  2018-08-13 15:53 ` [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too Jens Wiklander
  2018-08-13 15:53 ` [U-Boot] [PATCH 02/10] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-16 12:13   ` Igor Opaniuk
  2018-08-13 15:53 ` [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Adds mmc_rpmb_route_frames() to route RPMB data frames from/to an
external entity.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 drivers/mmc/rpmb.c | 160 +++++++++++++++++++++++++++++++++++++++++++++
 include/mmc.h      |   2 +
 2 files changed, 162 insertions(+)

diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
index dfbdb0deb107..908f19208955 100644
--- a/drivers/mmc/rpmb.c
+++ b/drivers/mmc/rpmb.c
@@ -321,3 +321,163 @@ int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
 	}
 	return i;
 }
+
+static int send_write_mult_block(struct mmc *mmc, const struct s_rpmb *frm,
+				 unsigned short cnt)
+{
+	struct mmc_cmd cmd = {
+		.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK,
+		.resp_type = MMC_RSP_R1b,
+	};
+	struct mmc_data data = {
+		.src = (const void *)frm,
+		.blocks = cnt,
+		.blocksize = sizeof(*frm),
+		.flags = MMC_DATA_WRITE,
+	};
+
+	return mmc_send_cmd(mmc, &cmd, &data);
+}
+
+static int send_read_mult_block(struct mmc *mmc, struct s_rpmb *frm,
+				unsigned short cnt)
+{
+	struct mmc_cmd cmd = {
+		.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK,
+		.resp_type = MMC_RSP_R1,
+	};
+	struct mmc_data data = {
+		.dest = (void *)frm,
+		.blocks = cnt,
+		.blocksize = sizeof(*frm),
+		.flags = MMC_DATA_READ,
+	};
+
+	return mmc_send_cmd(mmc, &cmd, &data);
+}
+
+static int rpmb_route_write_req(struct mmc *mmc, struct s_rpmb *req,
+				unsigned short req_cnt, struct s_rpmb *rsp,
+				unsigned short rsp_cnt)
+{
+	int ret;
+
+	/*
+	 * Send the write request.
+	 */
+	ret = mmc_set_blockcount(mmc, req_cnt, true);
+	if (ret)
+		return ret;
+
+	ret = send_write_mult_block(mmc, req, req_cnt);
+	if (ret)
+		return ret;
+
+	/*
+	 * Read the result of the request.
+	 */
+	ret = mmc_set_blockcount(mmc, 1, false);
+	if (ret)
+		return ret;
+
+	memset(rsp, 0, sizeof(*rsp));
+	rsp->request = cpu_to_be16(RPMB_REQ_STATUS);
+	ret = send_write_mult_block(mmc, rsp, 1);
+	if (ret)
+		return ret;
+
+	ret = mmc_set_blockcount(mmc, 1, false);
+	if (ret)
+		return ret;
+
+	return send_read_mult_block(mmc, rsp, 1);
+}
+
+static int rpmb_route_read_req(struct mmc *mmc, struct s_rpmb *req,
+			       unsigned short req_cnt, struct s_rpmb *rsp,
+			       unsigned short rsp_cnt)
+{
+	int ret;
+
+	/*
+	 * Send the read request.
+	 */
+	ret = mmc_set_blockcount(mmc, 1, false);
+	if (ret)
+		return ret;
+
+	ret = send_write_mult_block(mmc, req, 1);
+	if (ret)
+		return ret;
+
+	/*
+	 * Read the result of the request.
+	 */
+
+	ret = mmc_set_blockcount(mmc, rsp_cnt, false);
+	if (ret)
+		return ret;
+
+	return send_read_mult_block(mmc, rsp, rsp_cnt);
+}
+
+static int rpmb_route_frames(struct mmc *mmc, struct s_rpmb *req,
+			     unsigned short req_cnt, struct s_rpmb *rsp,
+			     unsigned short rsp_cnt)
+{
+	unsigned short n;
+
+	/*
+	 * If multiple request frames are provided, make sure that all are
+	 * of the same type.
+	 */
+	for (n = 1; n < req_cnt; n++)
+		if (req[n].request != req->request)
+			return -EINVAL;
+
+	switch (be16_to_cpu(req->request)) {
+	case RPMB_REQ_KEY:
+		if (req_cnt != 1 || rsp_cnt != 1)
+			return -EINVAL;
+		return rpmb_route_write_req(mmc, req, req_cnt, rsp, rsp_cnt);
+
+	case RPMB_REQ_WRITE_DATA:
+		if (!req_cnt || rsp_cnt != 1)
+			return -EINVAL;
+		return rpmb_route_write_req(mmc, req, req_cnt, rsp, rsp_cnt);
+
+	case RPMB_REQ_WCOUNTER:
+		if (req_cnt != 1 || rsp_cnt != 1)
+			return -EINVAL;
+		return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
+
+	case RPMB_REQ_READ_DATA:
+		if (req_cnt != 1 || !req_cnt)
+			return -EINVAL;
+		return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
+
+	default:
+		debug("Unsupported message type: %d\n",
+		      be16_to_cpu(req->request));
+		return -EINVAL;
+	}
+}
+
+int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
+			  void *rsp, unsigned long rsplen)
+{
+	/*
+	 * Whoever crafted the data supplied to this function knows how to
+	 * format the PRMB frames and which response is expected. If
+	 * there's some unexpected mismatch it's more helpful to report an
+	 * error immediately than trying to guess what was the intention
+	 * and possibly just delay an eventual error which will be harder
+	 * to track down.
+	 */
+
+	if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb))
+		return -EINVAL;
+
+	return rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
+				 rsp, rsplen / sizeof(struct s_rpmb));
+}
diff --git a/include/mmc.h b/include/mmc.h
index df4255b828a7..d6e02af4edea 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -748,6 +748,8 @@ int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
 		  unsigned short cnt, unsigned char *key);
 int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
 		   unsigned short cnt, unsigned char *key);
+int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
+			  void *rsp, unsigned long rsplen);
 #ifdef CONFIG_CMD_BKOPS_ENABLE
 int mmc_set_bkops_enable(struct mmc *mmc);
 #endif
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (2 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-16 12:14   ` Igor Opaniuk
                     ` (2 more replies)
  2018-08-13 15:53 ` [U-Boot] [PATCH 05/10] dt/bindings: add bindings for optee Jens Wiklander
                   ` (6 subsequent siblings)
  10 siblings, 3 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Adds a uclass to interface with a TEE (Trusted Execution Environment).

A TEE driver is a driver that interfaces with a trusted OS running in
some secure environment, for example, TrustZone on ARM cpus, or a
separate secure co-processor etc.

The TEE subsystem can serve a TEE driver for a Global Platform compliant
TEE, but it's not limited to only Global Platform TEEs.

The over all design is based on the TEE subsystem in the Linux kernel,
tailored for U-boot.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 MAINTAINERS              |   6 ++
 drivers/Kconfig          |   2 +
 drivers/Makefile         |   1 +
 drivers/tee/Kconfig      |   8 ++
 drivers/tee/Makefile     |   3 +
 drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
 include/dm/uclass-id.h   |   1 +
 include/tee.h            | 134 +++++++++++++++++++++++++++++
 8 files changed, 335 insertions(+)
 create mode 100644 drivers/tee/Kconfig
 create mode 100644 drivers/tee/Makefile
 create mode 100644 drivers/tee/tee-uclass.c
 create mode 100644 include/tee.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 58b61ac05882..7458c606ee92 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -571,6 +571,12 @@ TQ GROUP
 S:	Orphaned (Since 2016-02)
 T:	git git://git.denx.de/u-boot-tq-group.git
 
+TEE
+M:	Jens Wiklander <jens.wiklander@linaro.org>
+S:	Maintained
+F:	drivers/tee/
+F:	include/tee.h
+
 UBI
 M:	Kyungmin Park <kmpark@infradead.org>
 M:	Heiko Schocher <hs@denx.de>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index c72abf893297..f3249ab1d143 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
 
 source "drivers/sysreset/Kconfig"
 
+source "drivers/tee/Kconfig"
+
 source "drivers/thermal/Kconfig"
 
 source "drivers/timer/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index d53208540ea6..0fcae36f50f7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -103,6 +103,7 @@ obj-y += smem/
 obj-y += soc/
 obj-$(CONFIG_REMOTEPROC) += remoteproc/
 obj-y += thermal/
+obj-$(CONFIG_TEE) += tee/
 
 obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
 endif
diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
new file mode 100644
index 000000000000..817ab331b0f8
--- /dev/null
+++ b/drivers/tee/Kconfig
@@ -0,0 +1,8 @@
+# Generic Trusted Execution Environment Configuration
+config TEE
+	bool "Trusted Execution Environment support"
+	depends on ARM && (ARM64 || CPU_V7A)
+	select ARM_SMCCC
+	help
+	  This implements a generic interface towards a Trusted Execution
+	  Environment (TEE).
diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
new file mode 100644
index 000000000000..b6d8e16e6211
--- /dev/null
+++ b/drivers/tee/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += tee-uclass.o
diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
new file mode 100644
index 000000000000..f0243a0f2e4e
--- /dev/null
+++ b/drivers/tee/tee-uclass.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <tee.h>
+
+struct tee_uclass_priv {
+	struct list_head list_shm;
+};
+
+static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
+{
+	return device_get_ops(dev);
+}
+
+void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
+{
+	tee_get_ops(dev)->get_version(dev, vers);
+}
+
+int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
+		     ulong num_param, struct tee_param *param)
+{
+	return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
+}
+
+int tee_close_session(struct udevice *dev, u32 session)
+{
+	return tee_get_ops(dev)->close_session(dev, session);
+}
+
+int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
+		    ulong num_param, struct tee_param *param)
+{
+	return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
+}
+
+struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
+			      ulong size, u32 flags)
+{
+	struct tee_shm *shm;
+	void *p = addr;
+
+	if (flags & TEE_SHM_ALLOC) {
+		if (align)
+			p = memalign(align, size);
+		else
+			p = malloc(size);
+	}
+	if (!p)
+		return NULL;
+
+	shm = calloc(1, sizeof(*shm));
+	if (!shm)
+		goto err;
+
+	shm->dev = dev;
+	shm->addr = p;
+	shm->size = size;
+	shm->flags = flags;
+
+	if ((flags & TEE_SHM_SEC_REGISTER) &&
+	    tee_get_ops(dev)->shm_register(dev, shm))
+		goto err;
+
+	if (flags & TEE_SHM_REGISTER) {
+		struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
+
+		list_add(&shm->link, &priv->list_shm);
+	}
+	return shm;
+err:
+	free(shm);
+	if (flags & TEE_SHM_ALLOC)
+		free(p);
+	return NULL;
+}
+
+struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
+			      u32 flags)
+{
+	u32 f = flags;
+
+	f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
+	return __tee_shm_add(dev, 0, NULL, size, f);
+}
+
+struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
+				 ulong size, u32 flags)
+{
+	u32 f = flags & ~TEE_SHM_ALLOC;
+
+	f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
+	return __tee_shm_add(dev, 0, addr, size, f);
+}
+
+void tee_shm_free(struct tee_shm *shm)
+{
+	if (!shm)
+		return;
+
+	if (shm->flags & TEE_SHM_SEC_REGISTER)
+		tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
+
+	if (shm->flags & TEE_SHM_REGISTER)
+		list_del(&shm->link);
+
+	if (shm->flags & TEE_SHM_ALLOC)
+		free(shm->addr);
+
+	free(shm);
+}
+
+bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
+{
+	struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
+	struct tee_shm *s;
+
+	list_for_each_entry(s, &priv->list_shm, link)
+		if (s == shm)
+			return true;
+
+	return false;
+}
+
+struct udevice *tee_find_device(struct udevice *start,
+				int (*match)(struct tee_version_data *vers,
+					     const void *data),
+				const void *data,
+				struct tee_version_data *vers)
+{
+	struct udevice *dev = start;
+	struct tee_version_data lv;
+	struct tee_version_data *v = vers ? vers : &lv;
+
+	if (!dev)
+		uclass_first_device(UCLASS_TEE, &dev);
+
+	for (; dev; uclass_next_device(&dev)) {
+		tee_get_ops(dev)->get_version(dev, v);
+		if (!match || match(v, data))
+			return dev;
+	}
+
+	return NULL;
+}
+
+static int tee_pre_probe(struct udevice *dev)
+{
+	struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
+
+	INIT_LIST_HEAD(&priv->list_shm);
+	return 0;
+}
+
+static int tee_pre_remove(struct udevice *dev)
+{
+	struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
+	struct tee_shm *shm;
+
+	while (!list_empty(&priv->list_shm)) {
+		shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
+		debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
+		      __func__, (void *)shm, shm->size, shm->flags);
+		tee_shm_free(shm);
+	}
+
+	return 0;
+}
+
+UCLASS_DRIVER(tee) = {
+	.id = UCLASS_TEE,
+	.name = "tee",
+	.per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
+	.pre_probe = tee_pre_probe,
+	.pre_remove = tee_pre_remove,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a39643ec5eef..955e0a915b87 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -81,6 +81,7 @@ enum uclass_id {
 	UCLASS_SPI_GENERIC,	/* Generic SPI flash target */
 	UCLASS_SYSCON,		/* System configuration device */
 	UCLASS_SYSRESET,	/* System reset device */
+	UCLASS_TEE,		/* Trusted Execution Environment device */
 	UCLASS_THERMAL,		/* Thermal sensor */
 	UCLASS_TIMER,		/* Timer device */
 	UCLASS_TPM,		/* Trusted Platform Module TIS interface */
diff --git a/include/tee.h b/include/tee.h
new file mode 100644
index 000000000000..c2ac13e34128
--- /dev/null
+++ b/include/tee.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#ifndef __TEE_H
+#define __TEE_H
+
+#include <common.h>
+#include <dm.h>
+
+#define TEE_UUID_LEN		16
+
+#define TEE_GEN_CAP_GP          BIT(0)	/* GlobalPlatform compliant TEE */
+#define TEE_GEN_CAP_REG_MEM     BIT(1)	/* Supports registering shared memory */
+
+#define TEE_SHM_REGISTER	BIT(0)
+#define TEE_SHM_SEC_REGISTER	BIT(1)
+#define TEE_SHM_ALLOC		BIT(2)
+
+#define TEE_PARAM_ATTR_TYPE_NONE		0	/* parameter not used */
+#define TEE_PARAM_ATTR_TYPE_VALUE_INPUT		1
+#define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT	2
+#define TEE_PARAM_ATTR_TYPE_VALUE_INOUT		3	/* input and output */
+#define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT	5
+#define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT	6
+#define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT	7	/* input and output */
+#define TEE_PARAM_ATTR_TYPE_MASK		0xff
+#define TEE_PARAM_ATTR_META			0x100
+#define TEE_PARAM_ATTR_MASK			(TEE_PARAM_ATTR_TYPE_MASK | \
+						 TEE_PARAM_ATTR_META)
+
+/*
+ * Some Global Platform error codes which has a meaning if the
+ * TEE_GEN_CAP_GP bit is returned by the driver.
+ */
+#define TEE_SUCCESS			0x00000000
+#define TEE_ERROR_GENERIC		0xffff0000
+#define TEE_ERROR_BAD_PARAMETERS	0xffff0006
+#define TEE_ERROR_ITEM_NOT_FOUND	0xffff0008
+#define TEE_ERROR_NOT_IMPLEMENTED	0xffff0009
+#define TEE_ERROR_NOT_SUPPORTED		0xffff000a
+#define TEE_ERROR_COMMUNICATION		0xffff000e
+#define TEE_ERROR_OUT_OF_MEMORY		0xffff000c
+#define TEE_ERROR_TARGET_DEAD		0xffff3024
+
+#define TEE_ORIGIN_COMMS		0x00000002
+
+struct tee_driver_ops;
+
+struct tee_shm {
+	struct udevice *dev;
+	struct list_head link;
+	void *addr;
+	ulong size;
+	u32 flags;
+};
+
+struct tee_param_memref {
+	ulong shm_offs;
+	ulong size;
+	struct tee_shm *shm;
+};
+
+struct tee_param_value {
+	u64 a;
+	u64 b;
+	u64 c;
+};
+
+struct tee_param {
+	u64 attr;
+	union {
+		struct tee_param_memref memref;
+		struct tee_param_value value;
+	} u;
+};
+
+struct tee_open_session_arg {
+	u8 uuid[TEE_UUID_LEN];
+	u8 clnt_uuid[TEE_UUID_LEN];
+	u32 clnt_login;
+	u32 session;
+	u32 ret;
+	u32 ret_origin;
+};
+
+struct tee_invoke_arg {
+	u32 func;
+	u32 session;
+	u32 ret;
+	u32 ret_origin;
+};
+
+struct tee_version_data {
+	u32 gen_caps;
+};
+
+struct tee_driver_ops {
+	void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
+	int (*open_session)(struct udevice *dev,
+			    struct tee_open_session_arg *arg, ulong num_param,
+			    struct tee_param *param);
+	int (*close_session)(struct udevice *dev, u32 session);
+	int (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
+			   ulong num_param, struct tee_param *param);
+	int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
+	int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
+};
+
+struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
+			      ulong size, u32 flags);
+struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);
+struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
+				 ulong length, u32 flags);
+void tee_shm_free(struct tee_shm *shm);
+bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
+
+struct udevice *tee_find_device(struct udevice *start,
+				int (*match)(struct tee_version_data *vers,
+					     const void *data),
+				const void *data,
+				struct tee_version_data *vers);
+
+void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
+int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
+		     ulong num_param, struct tee_param *param);
+
+int tee_close_session(struct udevice *dev, u32 session);
+
+int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
+		    ulong num_param, struct tee_param *param);
+
+#endif /*__TEE_H*/
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 05/10] dt/bindings: add bindings for optee
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (3 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-13 15:53 ` [U-Boot] [PATCH 06/10] tee: add OP-TEE driver Jens Wiklander
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Sync with c8bfafb15944 ("dt/bindings: add bindings for optee")
from Linux kernel.

Introduces linaro prefix and adds bindings for ARM TrustZone based OP-TEE
implementation.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 .../firmware/linaro,optee-tz.txt              | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt

diff --git a/doc/device-tree-bindings/firmware/linaro,optee-tz.txt b/doc/device-tree-bindings/firmware/linaro,optee-tz.txt
new file mode 100644
index 000000000000..d38834c67dff
--- /dev/null
+++ b/doc/device-tree-bindings/firmware/linaro,optee-tz.txt
@@ -0,0 +1,31 @@
+OP-TEE Device Tree Bindings
+
+OP-TEE is a piece of software using hardware features to provide a Trusted
+Execution Environment. The security can be provided with ARM TrustZone, but
+also by virtualization or a separate chip.
+
+We're using "linaro" as the first part of the compatible property for
+the reference implementation maintained by Linaro.
+
+* OP-TEE based on ARM TrustZone required properties:
+
+- compatible     : should contain "linaro,optee-tz"
+
+- method         : The method of calling the OP-TEE Trusted OS. Permitted
+                   values are:
+
+                   "smc" : SMC #0, with the register assignments specified
+		           in drivers/tee/optee/optee_smc.h
+
+                   "hvc" : HVC #0, with the register assignments specified
+		           in drivers/tee/optee/optee_smc.h
+
+
+
+Example:
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 06/10] tee: add OP-TEE driver
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (4 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 05/10] dt/bindings: add bindings for optee Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-16 12:17   ` Igor Opaniuk
  2018-08-13 15:53 ` [U-Boot] [PATCH 07/10] arm: dt: hikey: Add optee node Jens Wiklander
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Adds a OP-TEE driver.

* Targets ARM and ARM64
* Supports using any u-boot memory as shared memory
* Probes OP-TEE version using SMCs
* Uses OPTEE message protocol version 2 to communicate with secure world

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 drivers/tee/Kconfig                      |  10 +
 drivers/tee/Makefile                     |   1 +
 drivers/tee/optee/Kconfig                |   7 +
 drivers/tee/optee/Makefile               |   4 +
 drivers/tee/optee/core.c                 | 614 +++++++++++++++++++++++
 drivers/tee/optee/optee_msg.h            | 423 ++++++++++++++++
 drivers/tee/optee/optee_msg_supplicant.h | 234 +++++++++
 drivers/tee/optee/optee_private.h        |  12 +
 drivers/tee/optee/optee_smc.h            | 444 ++++++++++++++++
 drivers/tee/optee/supplicant.c           |  89 ++++
 10 files changed, 1838 insertions(+)
 create mode 100644 drivers/tee/optee/Kconfig
 create mode 100644 drivers/tee/optee/Makefile
 create mode 100644 drivers/tee/optee/core.c
 create mode 100644 drivers/tee/optee/optee_msg.h
 create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
 create mode 100644 drivers/tee/optee/optee_private.h
 create mode 100644 drivers/tee/optee/optee_smc.h
 create mode 100644 drivers/tee/optee/supplicant.c

diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
index 817ab331b0f8..3e7fe6ddcc5d 100644
--- a/drivers/tee/Kconfig
+++ b/drivers/tee/Kconfig
@@ -6,3 +6,13 @@ config TEE
 	help
 	  This implements a generic interface towards a Trusted Execution
 	  Environment (TEE).
+
+if TEE
+
+menu "TEE drivers"
+
+source "drivers/tee/optee/Kconfig"
+
+endmenu
+
+endif
diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
index b6d8e16e6211..19633b60f235 100644
--- a/drivers/tee/Makefile
+++ b/drivers/tee/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 obj-y += tee-uclass.o
+obj-$(CONFIG_OPTEE) += optee/
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
new file mode 100644
index 000000000000..8f7ebe161111
--- /dev/null
+++ b/drivers/tee/optee/Kconfig
@@ -0,0 +1,7 @@
+# OP-TEE Trusted Execution Environment Configuration
+config OPTEE
+	bool "OP-TEE"
+	depends on ARM_SMCCC
+	help
+	  This implements the OP-TEE Trusted Execution Environment (TEE)
+	  driver.
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
new file mode 100644
index 000000000000..6148feb474a5
--- /dev/null
+++ b/drivers/tee/optee/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += core.o
+obj-y += supplicant.o
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
new file mode 100644
index 000000000000..a810f3b965de
--- /dev/null
+++ b/drivers/tee/optee/core.c
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.h>
+#include <log.h>
+#include <tee.h>
+
+#include "optee_smc.h"
+#include "optee_msg.h"
+#include "optee_private.h"
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+	((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
+
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+			       unsigned long, unsigned long, unsigned long,
+			       unsigned long, unsigned long,
+			       struct arm_smccc_res *);
+
+struct optee_pdata {
+	optee_invoke_fn *invoke_fn;
+};
+
+struct rpc_param {
+	u32	a0;
+	u32	a1;
+	u32	a2;
+	u32	a3;
+	u32	a4;
+	u32	a5;
+	u32	a6;
+	u32	a7;
+};
+
+static void *reg_pair_to_ptr(u32 reg0, u32 reg1)
+{
+	return (void *)(ulong)(((u64)reg0 << 32) | reg1);
+}
+
+static void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
+{
+	*reg0 = val >> 32;
+	*reg1 = val;
+}
+
+void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr)
+{
+	const unsigned int page_size = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+	const phys_addr_t page_mask = page_size - 1;
+	u8 *buf_base;
+	unsigned int page_offset;
+	unsigned int num_pages;
+	unsigned int list_size;
+	unsigned int n;
+	void *page_list;
+	struct {
+		u64 pages_list[PAGELIST_ENTRIES_PER_PAGE];
+		u64 next_page_data;
+	} *pages_data;
+
+	page_offset = (ulong)buf & page_mask;
+	num_pages = roundup(page_offset + len, page_size) / page_size;
+	list_size = DIV_ROUND_UP(num_pages, PAGELIST_ENTRIES_PER_PAGE) *
+		    page_size;
+	page_list = memalign(page_size, list_size);
+	if (!page_list)
+		return NULL;
+
+	pages_data = page_list;
+	buf_base = (u8 *)(rounddown((ulong)buf, page_size));
+	n = 0;
+	while (num_pages) {
+		pages_data->pages_list[n] = virt_to_phys(buf_base);
+		n++;
+		buf_base += page_size;
+		num_pages--;
+
+		if (n == PAGELIST_ENTRIES_PER_PAGE) {
+			pages_data->next_page_data =
+				virt_to_phys(pages_data + 1);
+			pages_data++;
+			n = 0;
+		}
+	}
+
+	*phys_buf_ptr = virt_to_phys(page_list) | page_offset;
+	return page_list;
+}
+
+static void optee_get_version(struct udevice *dev,
+			      struct tee_version_data *vers)
+{
+	struct tee_version_data v = {
+		.gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
+	};
+
+	*vers = v;
+}
+
+static struct tee_shm *get_msg_arg(struct udevice *dev, ulong num_params,
+				   struct optee_msg_arg **msg_arg)
+{
+	struct tee_shm *shm;
+	struct optee_msg_arg *ma;
+
+	shm = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
+			    OPTEE_MSG_GET_ARG_SIZE(num_params), TEE_SHM_ALLOC);
+	if (!shm)
+		return NULL;
+
+	ma = shm->addr;
+	memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
+	ma->num_params = num_params;
+	*msg_arg = ma;
+
+	return shm;
+}
+
+int to_msg_param(struct optee_msg_param *msg_params, ulong num_params,
+		 const struct tee_param *params)
+{
+	ulong n;
+
+	for (n = 0; n < num_params; n++) {
+		const struct tee_param *p = params + n;
+		struct optee_msg_param *mp = msg_params + n;
+
+		switch (p->attr) {
+		case TEE_PARAM_ATTR_TYPE_NONE:
+			mp->attr = OPTEE_MSG_ATTR_TYPE_NONE;
+			memset(&mp->u, 0, sizeof(mp->u));
+			break;
+		case TEE_PARAM_ATTR_TYPE_VALUE_INPUT:
+		case TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+		case TEE_PARAM_ATTR_TYPE_VALUE_INOUT:
+			mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+				   TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+			mp->u.value.a = p->u.value.a;
+			mp->u.value.b = p->u.value.b;
+			mp->u.value.c = p->u.value.c;
+			break;
+		case TEE_PARAM_ATTR_TYPE_MEMREF_INPUT:
+		case TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+		case TEE_PARAM_ATTR_TYPE_MEMREF_INOUT:
+			mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
+				   TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+			mp->u.rmem.shm_ref = (ulong)p->u.memref.shm;
+			mp->u.rmem.size = p->u.memref.size;
+			mp->u.rmem.offs = p->u.memref.shm_offs;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int from_msg_param(struct tee_param *params, ulong num_params,
+			  const struct optee_msg_param *msg_params)
+{
+	ulong n;
+	struct tee_shm *shm;
+
+	for (n = 0; n < num_params; n++) {
+		struct tee_param *p = params + n;
+		const struct optee_msg_param *mp = msg_params + n;
+		u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
+
+		switch (attr) {
+		case OPTEE_MSG_ATTR_TYPE_NONE:
+			p->attr = TEE_PARAM_ATTR_TYPE_NONE;
+			memset(&p->u, 0, sizeof(p->u));
+			break;
+		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+			p->attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT + attr -
+				  OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+			p->u.value.a = mp->u.value.a;
+			p->u.value.b = mp->u.value.b;
+			p->u.value.c = mp->u.value.c;
+			break;
+		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+			p->attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT + attr -
+				  OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+			p->u.memref.size = mp->u.rmem.size;
+			shm = (struct tee_shm *)(ulong)mp->u.rmem.shm_ref;
+
+			if (!shm) {
+				p->u.memref.shm_offs = 0;
+				p->u.memref.shm = NULL;
+				break;
+			}
+			p->u.memref.shm_offs = mp->u.rmem.offs;
+			p->u.memref.shm = shm;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static void handle_rpc(struct udevice *dev, struct rpc_param *param,
+		       void *page_list)
+{
+	struct tee_shm *shm;
+
+	switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
+	case OPTEE_SMC_RPC_FUNC_ALLOC:
+		shm = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
+				    param->a1,
+				    TEE_SHM_ALLOC | TEE_SHM_REGISTER);
+		if (shm) {
+			reg_pair_from_64(&param->a1, &param->a2,
+					 virt_to_phys(shm->addr));
+			/* "cookie" */
+			reg_pair_from_64(&param->a4, &param->a5, (ulong)shm);
+		} else {
+			param->a1 = 0;
+			param->a2 = 0;
+			param->a4 = 0;
+			param->a5 = 0;
+		}
+		break;
+	case OPTEE_SMC_RPC_FUNC_FREE:
+		shm = reg_pair_to_ptr(param->a1, param->a2);
+		tee_shm_free(shm);
+		break;
+	case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
+		break;
+	case OPTEE_SMC_RPC_FUNC_CMD:
+		shm = reg_pair_to_ptr(param->a1, param->a2);
+		optee_suppl_cmd(dev, shm, page_list);
+		break;
+	default:
+		break;
+	}
+
+	param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+}
+
+static u32 call_err_to_res(u32 call_err)
+{
+	switch (call_err) {
+	case OPTEE_SMC_RETURN_OK:
+		return TEE_SUCCESS;
+	default:
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+}
+
+static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg)
+{
+	struct optee_pdata *pdata = dev_get_platdata(dev);
+	struct rpc_param param = { .a0 = OPTEE_SMC_CALL_WITH_ARG };
+	void *page_list = NULL;
+
+	reg_pair_from_64(&param.a1, &param.a2, virt_to_phys(arg));
+	while (true) {
+		struct arm_smccc_res res;
+
+		pdata->invoke_fn(param.a0, param.a1, param.a2, param.a3,
+				 param.a4, param.a5, param.a6, param.a7, &res);
+
+		free(page_list);
+		page_list = NULL;
+
+		if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
+			param.a0 = res.a0;
+			param.a1 = res.a1;
+			param.a2 = res.a2;
+			param.a3 = res.a3;
+			handle_rpc(dev, &param, &page_list);
+		} else {
+			return call_err_to_res(res.a0);
+		}
+	}
+}
+
+int optee_close_session(struct udevice *dev, u32 session)
+{
+	struct tee_shm *shm;
+	struct optee_msg_arg *msg_arg;
+
+	shm = get_msg_arg(dev, 0, &msg_arg);
+	if (!shm)
+		return -ENOMEM;
+
+	msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+	msg_arg->session = session;
+	do_call_with_arg(dev, msg_arg);
+
+	tee_shm_free(shm);
+	return 0;
+}
+
+static int optee_open_session(struct udevice *dev,
+			      struct tee_open_session_arg *arg,
+			      ulong num_params, struct tee_param *params)
+{
+	int rc;
+	struct tee_shm *shm;
+	struct optee_msg_arg *msg_arg;
+
+	shm = get_msg_arg(dev, num_params + 2, &msg_arg);
+	if (!shm)
+		return -ENOMEM;
+
+	msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
+	/*
+	 * Initialize and add the meta parameters needed when opening a
+	 * session.
+	 */
+	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+				  OPTEE_MSG_ATTR_META;
+	msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+				  OPTEE_MSG_ATTR_META;
+	memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
+	memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
+	msg_arg->params[1].u.value.c = arg->clnt_login;
+
+	rc = to_msg_param(msg_arg->params + 2, num_params, params);
+	if (rc)
+		goto out;
+
+	arg->ret = do_call_with_arg(dev, msg_arg);
+	if (arg->ret) {
+		arg->ret_origin = TEE_ORIGIN_COMMS;
+		goto out;
+	}
+
+	if (from_msg_param(params, num_params, msg_arg->params + 2)) {
+		arg->ret = TEE_ERROR_COMMUNICATION;
+		arg->ret_origin = TEE_ORIGIN_COMMS;
+		/* Close session again to avoid leakage */
+		optee_close_session(dev, msg_arg->session);
+		goto out;
+	}
+
+	arg->session = msg_arg->session;
+	arg->ret = msg_arg->ret;
+	arg->ret_origin = msg_arg->ret_origin;
+out:
+	tee_shm_free(shm);
+
+	return rc;
+}
+
+int optee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
+		      ulong num_params, struct tee_param *params)
+{
+	struct tee_shm *shm;
+	struct optee_msg_arg *msg_arg;
+	int rc;
+
+	shm = get_msg_arg(dev, num_params, &msg_arg);
+	if (!shm)
+		return -ENOMEM;
+	msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
+	msg_arg->func = arg->func;
+	msg_arg->session = arg->session;
+
+	rc = to_msg_param(msg_arg->params, num_params, params);
+	if (rc)
+		goto out;
+
+	arg->ret = do_call_with_arg(dev, msg_arg);
+	if (arg->ret) {
+		arg->ret_origin = TEE_ORIGIN_COMMS;
+		goto out;
+	}
+
+	if (from_msg_param(params, num_params, msg_arg->params)) {
+		arg->ret = TEE_ERROR_COMMUNICATION;
+		arg->ret_origin = TEE_ORIGIN_COMMS;
+		goto out;
+	}
+
+	arg->ret = msg_arg->ret;
+	arg->ret_origin = msg_arg->ret_origin;
+out:
+	tee_shm_free(shm);
+	return rc;
+}
+
+int optee_shm_register(struct udevice *dev, struct tee_shm *shm)
+{
+	struct tee_shm *shm_arg;
+	struct optee_msg_arg *msg_arg;
+	void *pl;
+	u64 ph_ptr;
+	int rc = 0;
+
+	shm_arg = get_msg_arg(dev, 1, &msg_arg);
+	if (!shm_arg)
+		return -ENOMEM;
+
+	pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr);
+	if (!pl) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM;
+	msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
+				OPTEE_MSG_ATTR_NONCONTIG;
+	msg_arg->params->u.tmem.buf_ptr = ph_ptr;
+	msg_arg->params->u.tmem.shm_ref = (ulong)shm;
+	msg_arg->params->u.tmem.size = shm->size;
+
+	if (do_call_with_arg(dev, msg_arg) || msg_arg->ret)
+		rc = -EINVAL;
+
+	free(pl);
+out:
+	tee_shm_free(shm_arg);
+	return rc;
+}
+
+int optee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
+{
+	struct tee_shm *shm_arg;
+	struct optee_msg_arg *msg_arg;
+	int rc = 0;
+
+	shm_arg = get_msg_arg(dev, 1, &msg_arg);
+	if (!shm_arg)
+		return -ENOMEM;
+
+	msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
+	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+	msg_arg->params[0].u.rmem.shm_ref = (ulong)shm;
+
+	if (do_call_with_arg(dev, msg_arg) || msg_arg->ret)
+		rc = -EINVAL;
+	tee_shm_free(shm_arg);
+	return rc;
+}
+
+static const struct tee_driver_ops optee_ops = {
+	.get_version = optee_get_version,
+	.open_session = optee_open_session,
+	.close_session = optee_close_session,
+	.invoke_func = optee_invoke_func,
+	.shm_register = optee_shm_register,
+	.shm_unregister = optee_shm_unregister,
+};
+
+static bool is_optee_api(optee_invoke_fn *invoke_fn)
+{
+	struct arm_smccc_res res;
+
+	invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+	return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+	       res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
+}
+
+static void print_os_revision(optee_invoke_fn *invoke_fn)
+{
+	union {
+		struct arm_smccc_res smccc;
+		struct optee_smc_call_get_os_revision_result result;
+	} res = {
+		.result = {
+		.build_id = 0
+		}
+	};
+
+	invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
+		  &res.smccc);
+
+	if (res.result.build_id)
+		debug("OP-TEE revision %lu.%lu (%08lx)\n", res.result.major,
+		      res.result.minor, res.result.build_id);
+	else
+		debug("OP-TEE revision %lu.%lu\n", res.result.major,
+		      res.result.minor);
+}
+
+static bool api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+	union {
+		struct arm_smccc_res smccc;
+		struct optee_smc_calls_revision_result result;
+	} res;
+
+	invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+	return res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+	       (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR;
+}
+
+static bool exchange_capabilities(optee_invoke_fn *invoke_fn, u32 *sec_caps)
+{
+	union {
+		struct arm_smccc_res smccc;
+		struct optee_smc_exchange_capabilities_result result;
+	} res;
+
+	invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES,
+		  OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0,
+		  &res.smccc);
+
+	if (res.result.status != OPTEE_SMC_RETURN_OK)
+		return false;
+
+	*sec_caps = res.result.capabilities;
+	return true;
+}
+
+/* Simple wrapper functions to be able to use a function pointer */
+static void optee_smccc_smc(unsigned long a0, unsigned long a1,
+			    unsigned long a2, unsigned long a3,
+			    unsigned long a4, unsigned long a5,
+			    unsigned long a6, unsigned long a7,
+			    struct arm_smccc_res *res)
+{
+	arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
+			    unsigned long a2, unsigned long a3,
+			    unsigned long a4, unsigned long a5,
+			    unsigned long a6, unsigned long a7,
+			    struct arm_smccc_res *res)
+{
+	arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+static optee_invoke_fn *get_invoke_func(struct udevice *dev)
+{
+	const char *method;
+
+	debug("optee: looking for conduit method in DT.\n");
+	method = ofnode_get_property(dev->node, "method", NULL);
+	if (!method) {
+		debug("optee: missing \"method\" property\n");
+		return ERR_PTR(-ENXIO);
+	}
+
+	if (!strcmp("hvc", method))
+		return optee_smccc_hvc;
+	else if (!strcmp("smc", method))
+		return optee_smccc_smc;
+
+	debug("optee: invalid \"method\" property: %s\n", method);
+	return ERR_PTR(-EINVAL);
+}
+
+static int optee_ofdata_to_platdata(struct udevice *dev)
+{
+	struct optee_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->invoke_fn = get_invoke_func(dev);
+	if (IS_ERR(pdata->invoke_fn))
+		return PTR_ERR(pdata->invoke_fn);
+
+	return 0;
+}
+
+static int optee_probe(struct udevice *dev)
+{
+	struct optee_pdata *pdata = dev_get_platdata(dev);
+	u32 sec_caps;
+
+	if (!is_optee_api(pdata->invoke_fn)) {
+		debug("%s: OP-TEE api uid mismatch\n", __func__);
+		return -ENOENT;
+	}
+
+	print_os_revision(pdata->invoke_fn);
+
+	if (!api_revision_is_compatible(pdata->invoke_fn)) {
+		debug("%s: OP-TEE api revision mismatch\n", __func__);
+		return -ENOENT;
+	}
+
+	/*
+	 * OP-TEE can use both shared memory via predefined pool or as
+	 * dynamic shared memory provided by normal world. To keep things
+	 * simple we're only using dynamic shared memory in this driver.
+	 */
+	if (!exchange_capabilities(pdata->invoke_fn, &sec_caps) ||
+	    !(sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)) {
+		debug("%s: OP-TEE capabilities mismatch\n", __func__);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id optee_match[] = {
+	{ .compatible = "linaro,optee-tz" },
+	{},
+};
+
+U_BOOT_DRIVER(optee) = {
+	.name = "optee",
+	.id = UCLASS_TEE,
+	.of_match = optee_match,
+	.ofdata_to_platdata = optee_ofdata_to_platdata,
+	.probe = optee_probe,
+	.ops = &optee_ops,
+	.platdata_auto_alloc_size = sizeof(struct optee_pdata),
+};
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
new file mode 100644
index 000000000000..ebc16aa8cc31
--- /dev/null
+++ b/drivers/tee/optee/optee_msg.h
@@ -0,0 +1,423 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2015-2018, Linaro Limited
+ */
+
+#ifndef _OPTEE_MSG_H
+#define _OPTEE_MSG_H
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+/*
+ * This file defines the OP-TEE message protocol used to communicate
+ * with an instance of OP-TEE running in secure world.
+ *
+ * This file is divided into three sections.
+ * 1. Formatting of messages.
+ * 2. Requests from normal world
+ * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
+ *    tee-supplicant.
+ */
+
+/*****************************************************************************
+ * Part 1 - formatting of messages
+ *****************************************************************************/
+
+#define OPTEE_MSG_ATTR_TYPE_NONE		0x0
+#define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT		0x1
+#define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT	0x2
+#define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT		0x3
+#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT		0x5
+#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT		0x6
+#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT		0x7
+#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT		0x9
+#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT		0xa
+#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT		0xb
+
+#define OPTEE_MSG_ATTR_TYPE_MASK		GENMASK(7, 0)
+
+/*
+ * Meta parameter to be absorbed by the Secure OS and not passed
+ * to the Trusted Application.
+ *
+ * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION.
+ */
+#define OPTEE_MSG_ATTR_META			BIT(8)
+
+/*
+ * Pointer to a list of pages used to register user-defined SHM buffer.
+ * Used with OPTEE_MSG_ATTR_TYPE_TMEM_*.
+ * buf_ptr should point to the beginning of the buffer. Buffer will contain
+ * list of page addresses. OP-TEE core can reconstruct contiguous buffer from
+ * that page addresses list. Page addresses are stored as 64 bit values.
+ * Last entry on a page should point to the next page of buffer.
+ * Every entry in buffer should point to a 4k page beginning (12 least
+ * significant bits must be equal to zero).
+ *
+ * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
+ * offset of the user buffer.
+ *
+ * So, entries should be placed like members of this structure:
+ *
+ * struct page_data {
+ *   uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1];
+ *   uint64_t next_page_data;
+ * };
+ *
+ * Structure is designed to exactly fit into the page size
+ * OPTEE_MSG_NONCONTIG_PAGE_SIZE which is a standard 4KB page.
+ *
+ * The size of 4KB is chosen because this is the smallest page size for ARM
+ * architectures. If REE uses larger pages, it should divide them to 4KB ones.
+ */
+#define OPTEE_MSG_ATTR_NONCONTIG		BIT(9)
+
+/*
+ * Memory attributes for caching passed with temp memrefs. The actual value
+ * used is defined outside the message protocol with the exception of
+ * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already
+ * defined for the memory range should be used. If optee_smc.h is used as
+ * bearer of this protocol OPTEE_SMC_SHM_* is used for values.
+ */
+#define OPTEE_MSG_ATTR_CACHE_SHIFT		16
+#define OPTEE_MSG_ATTR_CACHE_MASK		GENMASK(2, 0)
+#define OPTEE_MSG_ATTR_CACHE_PREDEFINED		0
+
+/*
+ * Same values as TEE_LOGIN_* from TEE Internal API
+ */
+#define OPTEE_MSG_LOGIN_PUBLIC			0x00000000
+#define OPTEE_MSG_LOGIN_USER			0x00000001
+#define OPTEE_MSG_LOGIN_GROUP			0x00000002
+#define OPTEE_MSG_LOGIN_APPLICATION		0x00000004
+#define OPTEE_MSG_LOGIN_APPLICATION_USER	0x00000005
+#define OPTEE_MSG_LOGIN_APPLICATION_GROUP	0x00000006
+
+/*
+ * Page size used in non-contiguous buffer entries
+ */
+#define OPTEE_MSG_NONCONTIG_PAGE_SIZE		4096
+
+/**
+ * struct optee_msg_param_tmem - temporary memory reference parameter
+ * @buf_ptr:	Address of the buffer
+ * @size:	Size of the buffer
+ * @shm_ref:	Temporary shared memory reference, pointer to a struct tee_shm
+ *
+ * Secure and normal world communicates pointers as physical address
+ * instead of the virtual address. This is because secure and normal world
+ * have completely independent memory mapping. Normal world can even have a
+ * hypervisor which need to translate the guest physical address (AKA IPA
+ * in ARM documentation) to a real physical address before passing the
+ * structure to secure world.
+ */
+struct optee_msg_param_tmem {
+	u64 buf_ptr;
+	u64 size;
+	u64 shm_ref;
+};
+
+/**
+ * struct optee_msg_param_rmem - registered memory reference parameter
+ * @offs:	Offset into shared memory reference
+ * @size:	Size of the buffer
+ * @shm_ref:	Shared memory reference, pointer to a struct tee_shm
+ */
+struct optee_msg_param_rmem {
+	u64 offs;
+	u64 size;
+	u64 shm_ref;
+};
+
+/**
+ * struct optee_msg_param_value - opaque value parameter
+ *
+ * Value parameters are passed unchecked between normal and secure world.
+ */
+struct optee_msg_param_value {
+	u64 a;
+	u64 b;
+	u64 c;
+};
+
+/**
+ * struct optee_msg_param - parameter used together with struct optee_msg_arg
+ * @attr:	attributes
+ * @tmem:	parameter by temporary memory reference
+ * @rmem:	parameter by registered memory reference
+ * @value:	parameter by opaque value
+ *
+ * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
+ * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
+ * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
+ * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
+ * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
+ */
+struct optee_msg_param {
+	u64 attr;
+	union {
+		struct optee_msg_param_tmem tmem;
+		struct optee_msg_param_rmem rmem;
+		struct optee_msg_param_value value;
+	} u;
+};
+
+/**
+ * struct optee_msg_arg - call argument
+ * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_*
+ * @func: Trusted Application function, specific to the Trusted Application,
+ *	     used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND
+ * @session: In parameter for all OPTEE_MSG_CMD_* except
+ *	     OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead
+ * @cancel_id: Cancellation id, a unique value to identify this request
+ * @ret: return value
+ * @ret_origin: origin of the return value
+ * @num_params: number of parameters supplied to the OS Command
+ * @params: the parameters supplied to the OS Command
+ *
+ * All normal calls to Trusted OS uses this struct. If cmd requires further
+ * information than what these field holds it can be passed as a parameter
+ * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
+ * attrs field). All parameters tagged as meta has to come first.
+ *
+ * Temp memref parameters can be fragmented if supported by the Trusted OS
+ * (when optee_smc.h is bearer of this protocol this is indicated with
+ * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
+ * fragmented then has all but the last fragment the
+ * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
+ * it will still be presented as a single logical memref to the Trusted
+ * Application.
+ */
+struct optee_msg_arg {
+	u32 cmd;
+	u32 func;
+	u32 session;
+	u32 cancel_id;
+	u32 pad;
+	u32 ret;
+	u32 ret_origin;
+	u32 num_params;
+
+	/* num_params tells the actual number of element in params */
+	struct optee_msg_param params[0];
+};
+
+/**
+ * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg
+ *
+ * @num_params: Number of parameters embedded in the struct optee_msg_arg
+ *
+ * Returns the size of the struct optee_msg_arg together with the number
+ * of embedded parameters.
+ */
+#define OPTEE_MSG_GET_ARG_SIZE(num_params) \
+	(sizeof(struct optee_msg_arg) + \
+	 sizeof(struct optee_msg_param) * (num_params))
+
+/*****************************************************************************
+ * Part 2 - requests from normal world
+ *****************************************************************************/
+
+/*
+ * Return the following UID if using API specified in this file without
+ * further extensions:
+ * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
+ * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
+ * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
+ */
+#define OPTEE_MSG_UID_0			0x384fb3e0
+#define OPTEE_MSG_UID_1			0xe7f811e3
+#define OPTEE_MSG_UID_2			0xaf630002
+#define OPTEE_MSG_UID_3			0xa5d5c51b
+#define OPTEE_MSG_FUNCID_CALLS_UID	0xFF01
+
+/*
+ * Returns 2.0 if using API specified in this file without further
+ * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR
+ * and OPTEE_MSG_REVISION_MINOR
+ */
+#define OPTEE_MSG_REVISION_MAJOR	2
+#define OPTEE_MSG_REVISION_MINOR	0
+#define OPTEE_MSG_FUNCID_CALLS_REVISION	0xFF03
+
+/*
+ * Get UUID of Trusted OS.
+ *
+ * Used by non-secure world to figure out which Trusted OS is installed.
+ * Note that returned UUID is the UUID of the Trusted OS, not of the API.
+ *
+ * Returns UUID in 4 32-bit words in the same way as
+ * OPTEE_MSG_FUNCID_CALLS_UID described above.
+ */
+#define OPTEE_MSG_OS_OPTEE_UUID_0	0x486178e0
+#define OPTEE_MSG_OS_OPTEE_UUID_1	0xe7f811e3
+#define OPTEE_MSG_OS_OPTEE_UUID_2	0xbc5e0002
+#define OPTEE_MSG_OS_OPTEE_UUID_3	0xa5d5c51b
+#define OPTEE_MSG_FUNCID_GET_OS_UUID	0x0000
+
+/*
+ * Get revision of Trusted OS.
+ *
+ * Used by non-secure world to figure out which version of the Trusted OS
+ * is installed. Note that the returned revision is the revision of the
+ * Trusted OS, not of the API.
+ *
+ * Returns revision in 2 32-bit words in the same way as
+ * OPTEE_MSG_CALLS_REVISION described above.
+ */
+#define OPTEE_MSG_FUNCID_GET_OS_REVISION	0x0001
+
+/*
+ * Do a secure call with struct optee_msg_arg as argument
+ * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
+ *
+ * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application.
+ * The first two parameters are tagged as meta, holding two value
+ * parameters to pass the following information:
+ * param[0].u.value.a-b uuid of Trusted Application
+ * param[1].u.value.a-b uuid of Client
+ * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_*
+ *
+ * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened
+ * session to a Trusted Application.  struct optee_msg_arg::func is Trusted
+ * Application function, specific to the Trusted Application.
+ *
+ * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to
+ * Trusted Application.
+ *
+ * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command.
+ *
+ * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
+ * information is passed as:
+ * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
+ *					[| OPTEE_MSG_ATTR_FRAGMENT]
+ * [in] param[0].u.tmem.buf_ptr		physical address (of first fragment)
+ * [in] param[0].u.tmem.size		size (of first fragment)
+ * [in] param[0].u.tmem.shm_ref		holds shared memory reference
+ * ...
+ * The shared memory can optionally be fragmented, temp memrefs can follow
+ * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
+ *
+ * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
+ * memory reference. The information is passed as:
+ * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
+ * [in] param[0].u.rmem.shm_ref		holds shared memory reference
+ * [in] param[0].u.rmem.offs		0
+ * [in] param[0].u.rmem.size		0
+ */
+#define OPTEE_MSG_CMD_OPEN_SESSION	0
+#define OPTEE_MSG_CMD_INVOKE_COMMAND	1
+#define OPTEE_MSG_CMD_CLOSE_SESSION	2
+#define OPTEE_MSG_CMD_CANCEL		3
+#define OPTEE_MSG_CMD_REGISTER_SHM	4
+#define OPTEE_MSG_CMD_UNREGISTER_SHM	5
+#define OPTEE_MSG_FUNCID_CALL_WITH_ARG	0x0004
+
+/*****************************************************************************
+ * Part 3 - Requests from secure world, RPC
+ *****************************************************************************/
+
+/*
+ * All RPC is done with a struct optee_msg_arg as bearer of information,
+ * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
+ *
+ * RPC communication with tee-supplicant is reversed compared to normal
+ * client communication desribed above. The supplicant receives requests
+ * and sends responses.
+ */
+
+/*
+ * Load a TA into memory, defined in tee-supplicant
+ */
+#define OPTEE_MSG_RPC_CMD_LOAD_TA	0
+
+/*
+ * Reserved
+ */
+#define OPTEE_MSG_RPC_CMD_RPMB		1
+
+/*
+ * File system access, defined in tee-supplicant
+ */
+#define OPTEE_MSG_RPC_CMD_FS		2
+
+/*
+ * Get time
+ *
+ * Returns number of seconds and nano seconds since the Epoch,
+ * 1970-01-01 00:00:00 +0000 (UTC).
+ *
+ * [out] param[0].u.value.a	Number of seconds
+ * [out] param[0].u.value.b	Number of nano seconds.
+ */
+#define OPTEE_MSG_RPC_CMD_GET_TIME	3
+
+/*
+ * Wait queue primitive, helper for secure world to implement a wait queue.
+ *
+ * If secure world need to wait for a secure world mutex it issues a sleep
+ * request instead of spinning in secure world. Conversely is a wakeup
+ * request issued when a secure world mutex with a thread waiting thread is
+ * unlocked.
+ *
+ * Waiting on a key
+ * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
+ * [in] param[0].u.value.b wait key
+ *
+ * Waking up a key
+ * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
+ * [in] param[0].u.value.b wakeup key
+ */
+#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE	4
+#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP	0
+#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP	1
+
+/*
+ * Suspend execution
+ *
+ * [in] param[0].value	.a number of milliseconds to suspend
+ */
+#define OPTEE_MSG_RPC_CMD_SUSPEND	5
+
+/*
+ * Allocate a piece of shared memory
+ *
+ * Shared memory can optionally be fragmented, to support that additional
+ * spare param entries are allocated to make room for eventual fragments.
+ * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
+ * unused. All returned temp memrefs except the last should have the
+ * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
+ *
+ * [in]  param[0].u.value.a		type of memory one of
+ *					OPTEE_MSG_RPC_SHM_TYPE_* below
+ * [in]  param[0].u.value.b		requested size
+ * [in]  param[0].u.value.c		required alignment
+ *
+ * [out] param[0].u.tmem.buf_ptr	physical address (of first fragment)
+ * [out] param[0].u.tmem.size		size (of first fragment)
+ * [out] param[0].u.tmem.shm_ref	shared memory reference
+ * ...
+ * [out] param[n].u.tmem.buf_ptr	physical address
+ * [out] param[n].u.tmem.size		size
+ * [out] param[n].u.tmem.shm_ref	shared memory reference (same value
+ *					as in param[n-1].u.tmem.shm_ref)
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_ALLOC	6
+/* Memory that can be shared with a non-secure user space application */
+#define OPTEE_MSG_RPC_SHM_TYPE_APPL	0
+/* Memory only shared with non-secure kernel */
+#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL	1
+
+/*
+ * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
+ *
+ * [in]  param[0].u.value.a		type of memory one of
+ *					OPTEE_MSG_RPC_SHM_TYPE_* above
+ * [in]  param[0].u.value.b		value of shared memory reference
+ *					returned in param[0].u.tmem.shm_ref
+ *					above
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_FREE	7
+
+#endif /* _OPTEE_MSG_H */
diff --git a/drivers/tee/optee/optee_msg_supplicant.h b/drivers/tee/optee/optee_msg_supplicant.h
new file mode 100644
index 000000000000..65ca6c0574b9
--- /dev/null
+++ b/drivers/tee/optee/optee_msg_supplicant.h
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2016-2018, Linaro Limited
+ */
+
+#ifndef __OPTEE_MSG_SUPPLICANT_H
+#define __OPTEE_MSG_SUPPLICANT_H
+
+/*
+ * Load a TA into memory
+ */
+#define OPTEE_MSG_RPC_CMD_LOAD_TA	0
+
+/*
+ * Replay Protected Memory Block access
+ */
+#define OPTEE_MSG_RPC_CMD_RPMB		1
+
+/*
+ * File system access
+ */
+#define OPTEE_MSG_RPC_CMD_FS		2
+
+/*
+ * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_FS and first
+ * parameter has the attribute OPTEE_MSG_ATTR_TYPE_VALUE_INPUT.
+ */
+
+/*
+ * Open a file
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRF_OPEN
+ * [in]     param[1].u.tmem	a string holding the file name
+ * [out]    param[2].u.value.a	file descriptor of open file
+ */
+#define OPTEE_MRF_OPEN			0
+
+/*
+ * Create a file
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRF_CREATE
+ * [in]     param[1].u.tmem	a string holding the file name
+ * [out]    param[2].u.value.a	file descriptor of open file
+ */
+#define OPTEE_MRF_CREATE		1
+
+/*
+ * Close a file
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRF_CLOSE
+ * [in]     param[0].u.value.b	file descriptor of open file.
+ */
+#define OPTEE_MRF_CLOSE			2
+
+/*
+ * Read from a file
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRF_READ
+ * [in]     param[0].u.value.b	file descriptor of open file
+ * [in]     param[0].u.value.c	offset into file
+ * [out]    param[1].u.tmem	buffer to hold returned data
+ */
+#define OPTEE_MRF_READ			3
+
+/*
+ * Write to a file
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRF_WRITE
+ * [in]     param[0].u.value.b	file descriptor of open file
+ * [in]     param[0].u.value.c	offset into file
+ * [in]     param[1].u.tmem	buffer holding data to be written
+ */
+#define OPTEE_MRF_WRITE			4
+
+/*
+ * Truncate a file
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRF_TRUNCATE
+ * [in]     param[0].u.value.b	file descriptor of open file
+ * [in]     param[0].u.value.c	length of file.
+ */
+#define OPTEE_MRF_TRUNCATE		5
+
+/*
+ * Remove a file
+ *
+ * [in]  param[0].u.value.a	OPTEE_MRF_REMOVE
+ * [in]  param[1].u.tmem	a string holding the file name
+ */
+#define OPTEE_MRF_REMOVE		6
+
+/*
+ * Rename a file
+ *
+ * [in]  param[0].u.value.a	OPTEE_MRF_RENAME
+ * [in]  param[0].u.value.b	true if existing target should be removed
+ * [in]  param[1].u.tmem	a string holding the old file name
+ * [in]  param[2].u.tmem	a string holding the new file name
+ */
+#define OPTEE_MRF_RENAME		7
+
+/*
+ * Opens a directory for file listing
+ *
+ * [in]  param[0].u.value.a	OPTEE_MRF_OPENDIR
+ * [in]  param[1].u.tmem	a string holding the name of the directory
+ * [out] param[2].u.value.a	handle to open directory
+ */
+#define OPTEE_MRF_OPENDIR		8
+
+/*
+ * Closes a directory handle
+ *
+ * [in]  param[0].u.value.a	OPTEE_MRF_CLOSEDIR
+ * [in]  param[0].u.value.b	handle to open directory
+ */
+#define OPTEE_MRF_CLOSEDIR		9
+
+/*
+ * Read next file name of directory
+ *
+ *
+ * [in]  param[0].u.value.a	OPTEE_MRF_READDIR
+ * [in]  param[0].u.value.b	handle to open directory
+ * [out] param[1].u.tmem	a string holding the file name
+ */
+#define OPTEE_MRF_READDIR		10
+
+/*
+ * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_FS
+ */
+
+/*
+ * Command Ids 3, 4 and 5 of OPTEE_MSG_RPC_CMD_xxx macros are reserved for use
+ * by the kernel driver.
+ */
+
+/*
+ * Shared memory allocation
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_ALLOC	6
+#define OPTEE_MSG_RPC_CMD_SHM_FREE	7
+
+/*
+ * Was OPTEE_MSG_RPC_CMD_SQL_FS, which isn't supported any longer
+ */
+#define OPTEE_MSG_RPC_CMD_SQL_FS_RESERVED	8
+
+/*
+ * GPROF support management commands
+ */
+#define OPTEE_MSG_RPC_CMD_GPROF		9
+
+/*
+ * Socket commands
+ */
+#define OPTEE_MSG_RPC_CMD_SOCKET	10
+
+/*
+ * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET
+ */
+
+#define OPTEE_MRC_SOCKET_TIMEOUT_NONBLOCKING	0
+#define OPTEE_MRC_SOCKET_TIMEOUT_BLOCKING	0xffffffff
+
+/*
+ * Open socket
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRC_SOCKET_OPEN
+ * [in]     param[0].u.value.b	TA instance id
+ * [in]     param[1].u.value.a	server port number
+ * [in]     param[1].u.value.b	protocol, TEE_ISOCKET_PROTOCOLID_*
+ * [in]     param[1].u.value.c	ip version TEE_IP_VERSION_* from tee_ipsocket.h
+ * [in]     param[2].u.tmem	server address
+ * [out]    param[3].u.value.a	socket handle (32-bit)
+ */
+#define OPTEE_MRC_SOCKET_OPEN	0
+
+/*
+ * Close socket
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRC_SOCKET_CLOSE
+ * [in]     param[0].u.value.b	TA instance id
+ * [in]     param[0].u.value.c	socket handle
+ */
+#define OPTEE_MRC_SOCKET_CLOSE	1
+
+/*
+ * Close all sockets
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRC_SOCKET_CLOSE_ALL
+ * [in]     param[0].u.value.b	TA instance id
+ */
+#define OPTEE_MRC_SOCKET_CLOSE_ALL 2
+
+/*
+ * Send data on socket
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRC_SOCKET_SEND
+ * [in]     param[0].u.value.b	TA instance id
+ * [in]     param[0].u.value.c	socket handle
+ * [in]     param[1].u.tmem	buffer to transmit
+ * [in]     param[2].u.value.a	timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_*
+ * [out]    param[2].u.value.b	number of transmitted bytes
+ */
+#define OPTEE_MRC_SOCKET_SEND	3
+
+/*
+ * Receive data on socket
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRC_SOCKET_RECV
+ * [in]     param[0].u.value.b	TA instance id
+ * [in]     param[0].u.value.c	socket handle
+ * [out]    param[1].u.tmem	buffer to receive
+ * [in]     param[2].u.value.a	timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_*
+ */
+#define OPTEE_MRC_SOCKET_RECV	4
+
+/*
+ * Perform IOCTL on socket
+ *
+ * [in]     param[0].u.value.a	OPTEE_MRC_SOCKET_IOCTL
+ * [in]     param[0].u.value.b	TA instance id
+ * [in]     param[0].u.value.c	socket handle
+ * [in/out] param[1].u.tmem	buffer
+ * [in]     param[2].u.value.a	ioctl command
+ */
+#define OPTEE_MRC_SOCKET_IOCTL	5
+
+/*
+ * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET
+ */
+
+#endif /*__OPTEE_MSG_SUPPLICANT_H*/
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
new file mode 100644
index 000000000000..daa470f812a9
--- /dev/null
+++ b/drivers/tee/optee/optee_private.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#ifndef __OPTEE_PRIVATE_H
+#define __OPTEE_PRIVATE_H
+
+void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr);
+void optee_suppl_cmd(struct udevice *dev, void *shm, void **page_list);
+
+#endif /*__OPTEE_PRIVATE_H*/
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
new file mode 100644
index 000000000000..81069ae6f8ac
--- /dev/null
+++ b/drivers/tee/optee/optee_smc.h
@@ -0,0 +1,444 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2015-2018, Linaro Limited
+ */
+
+#ifndef OPTEE_SMC_H
+#define OPTEE_SMC_H
+
+#include <linux/arm-smccc.h>
+#include <linux/bitops.h>
+
+#define OPTEE_SMC_STD_CALL_VAL(func_num) \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
+			   ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+#define OPTEE_SMC_FAST_CALL_VAL(func_num) \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+			   ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+
+/*
+ * Function specified by SMC Calling convention.
+ */
+#define OPTEE_SMC_FUNCID_CALLS_COUNT	0xFF00
+#define OPTEE_SMC_CALLS_COUNT \
+	ARM_SMCCC_CALL_VAL(OPTEE_SMC_FAST_CALL, SMCCC_SMC_32, \
+			   SMCCC_OWNER_TRUSTED_OS_END, \
+			   OPTEE_SMC_FUNCID_CALLS_COUNT)
+
+/*
+ * Normal cached memory (write-back), shareable for SMP systems and not
+ * shareable for UP systems.
+ */
+#define OPTEE_SMC_SHM_CACHED		1
+
+/*
+ * a0..a7 is used as register names in the descriptions below, on arm32
+ * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's
+ * 32-bit registers.
+ */
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * Return one of the following UIDs if using API specified in this file
+ * without further extentions:
+ * 65cb6b93-af0c-4617-8ed6-644a8d1140f8
+ * see also OPTEE_SMC_UID_* in optee_msg.h
+ */
+#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
+#define OPTEE_SMC_CALLS_UID \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+			   ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+			   OPTEE_SMC_FUNCID_CALLS_UID)
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * Returns 2.0 if using API specified in this file without further extentions.
+ * see also OPTEE_MSG_REVISION_* in optee_msg.h
+ */
+#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
+#define OPTEE_SMC_CALLS_REVISION \
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+			   ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+			   OPTEE_SMC_FUNCID_CALLS_REVISION)
+
+struct optee_smc_calls_revision_result {
+	unsigned long major;
+	unsigned long minor;
+	unsigned long reserved0;
+	unsigned long reserved1;
+};
+
+/*
+ * Get UUID of Trusted OS.
+ *
+ * Used by non-secure world to figure out which Trusted OS is installed.
+ * Note that returned UUID is the UUID of the Trusted OS, not of the API.
+ *
+ * Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID
+ * described above.
+ */
+#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID
+#define OPTEE_SMC_CALL_GET_OS_UUID \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID)
+
+/*
+ * Get revision of Trusted OS.
+ *
+ * Used by non-secure world to figure out which version of the Trusted OS
+ * is installed. Note that the returned revision is the revision of the
+ * Trusted OS, not of the API.
+ *
+ * Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION
+ * described above. May optionally return a 32-bit build identifier in a2,
+ * with zero meaning unspecified.
+ */
+#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION
+#define OPTEE_SMC_CALL_GET_OS_REVISION \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION)
+
+struct optee_smc_call_get_os_revision_result {
+	unsigned long major;
+	unsigned long minor;
+	unsigned long build_id;
+	unsigned long reserved1;
+};
+
+/*
+ * Call with struct optee_msg_arg as argument
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
+ * a1	Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
+ * a2	Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
+ * a3	Cache settings, not used if physical pointer is in a predefined shared
+ *	memory area else per OPTEE_SMC_SHM_*
+ * a4-6	Not used
+ * a7	Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0	Return value, OPTEE_SMC_RETURN_*
+ * a1-3	Not used
+ * a4-7	Preserved
+ *
+ * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage:
+ * a0	Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT
+ * a1-3	Preserved
+ * a4-7	Preserved
+ *
+ * RPC return register usage:
+ * a0	Return value, OPTEE_SMC_RETURN_IS_RPC(val)
+ * a1-2	RPC parameters
+ * a3-7	Resume information, must be preserved
+ *
+ * Possible return values:
+ * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION	Trusted OS does not recognize this
+ *					function.
+ * OPTEE_SMC_RETURN_OK			Call completed, result updated in
+ *					the previously supplied struct
+ *					optee_msg_arg.
+ * OPTEE_SMC_RETURN_ETHREAD_LIMIT	Number of Trusted OS threads exceeded,
+ *					try again later.
+ * OPTEE_SMC_RETURN_EBADADDR		Bad physcial pointer to struct
+ *					optee_msg_arg.
+ * OPTEE_SMC_RETURN_EBADCMD		Bad/unknown cmd in struct optee_msg_arg
+ * OPTEE_SMC_RETURN_IS_RPC()		Call suspended by RPC call to normal
+ *					world.
+ */
+#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG
+#define OPTEE_SMC_CALL_WITH_ARG \
+	OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG)
+
+/*
+ * Get Shared Memory Config
+ *
+ * Returns the Secure/Non-secure shared memory config.
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG
+ * a1-6	Not used
+ * a7	Hypervisor Client ID register
+ *
+ * Have config return register usage:
+ * a0	OPTEE_SMC_RETURN_OK
+ * a1	Physical address of start of SHM
+ * a2	Size of of SHM
+ * a3	Cache settings of memory, as defined by the
+ *	OPTEE_SMC_SHM_* values above
+ * a4-7	Preserved
+ *
+ * Not available register usage:
+ * a0	OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-3 Not used
+ * a4-7	Preserved
+ */
+#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG	7
+#define OPTEE_SMC_GET_SHM_CONFIG \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG)
+
+struct optee_smc_get_shm_config_result {
+	unsigned long status;
+	unsigned long start;
+	unsigned long size;
+	unsigned long settings;
+};
+
+/*
+ * Exchanges capabilities between normal world and secure world
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES
+ * a1	bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_*
+ * a2-6	Not used
+ * a7	Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0	OPTEE_SMC_RETURN_OK
+ * a1	bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
+ * a2-7	Preserved
+ *
+ * Error return register usage:
+ * a0	OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world
+ * a1	bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
+ * a2-7 Preserved
+ */
+/* Normal world works as a uniprocessor system */
+#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR		BIT(0)
+/* Secure world has reserved shared memory for normal world to use */
+#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM	BIT(0)
+/* Secure world can communicate via previously unregistered shared memory */
+#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM	BIT(1)
+
+/*
+ * Secure world supports commands "register/unregister shared memory",
+ * secure world accepts command buffers located in any parts of non-secure RAM
+ */
+#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM		BIT(2)
+
+#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES	9
+#define OPTEE_SMC_EXCHANGE_CAPABILITIES \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
+
+struct optee_smc_exchange_capabilities_result {
+	unsigned long status;
+	unsigned long capabilities;
+	unsigned long reserved0;
+	unsigned long reserved1;
+};
+
+/*
+ * Disable and empties cache of shared memory objects
+ *
+ * Secure world can cache frequently used shared memory objects, for
+ * example objects used as RPC arguments. When secure world is idle this
+ * function returns one shared memory reference to free. To disable the
+ * cache and free all cached objects this function has to be called until
+ * it returns OPTEE_SMC_RETURN_ENOTAVAIL.
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE
+ * a1-6	Not used
+ * a7	Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0	OPTEE_SMC_RETURN_OK
+ * a1	Upper 32bit of a 64bit Shared memory cookie
+ * a2	Lower 32bit of a 64bit Shared memory cookie
+ * a3-7	Preserved
+ *
+ * Cache empty return register usage:
+ * a0	OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-7	Preserved
+ *
+ * Not idle return register usage:
+ * a0	OPTEE_SMC_RETURN_EBUSY
+ * a1-7	Preserved
+ */
+#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE	10
+#define OPTEE_SMC_DISABLE_SHM_CACHE \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE)
+
+struct optee_smc_disable_shm_cache_result {
+	unsigned long status;
+	unsigned long shm_upper32;
+	unsigned long shm_lower32;
+	unsigned long reserved0;
+};
+
+/*
+ * Enable cache of shared memory objects
+ *
+ * Secure world can cache frequently used shared memory objects, for
+ * example objects used as RPC arguments. When secure world is idle this
+ * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If
+ * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned.
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE
+ * a1-6	Not used
+ * a7	Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0	OPTEE_SMC_RETURN_OK
+ * a1-7	Preserved
+ *
+ * Not idle return register usage:
+ * a0	OPTEE_SMC_RETURN_EBUSY
+ * a1-7	Preserved
+ */
+#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE	11
+#define OPTEE_SMC_ENABLE_SHM_CACHE \
+	OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
+
+/*
+ * Resume from RPC (for example after processing a foreign interrupt)
+ *
+ * Call register usage:
+ * a0	SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
+ * a1-3	Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned
+ *	OPTEE_SMC_RETURN_RPC in a0
+ *
+ * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above.
+ *
+ * Possible return values
+ * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION	Trusted OS does not recognize this
+ *					function.
+ * OPTEE_SMC_RETURN_OK			Original call completed, result
+ *					updated in the previously supplied.
+ *					struct optee_msg_arg
+ * OPTEE_SMC_RETURN_RPC			Call suspended by RPC call to normal
+ *					world.
+ * OPTEE_SMC_RETURN_ERESUME		Resume failed, the opaque resume
+ *					information was corrupt.
+ */
+#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC	3
+#define OPTEE_SMC_CALL_RETURN_FROM_RPC \
+	OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC)
+
+#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK	0xFFFF0000
+#define OPTEE_SMC_RETURN_RPC_PREFIX		0xFFFF0000
+#define OPTEE_SMC_RETURN_RPC_FUNC_MASK		0x0000FFFF
+
+#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \
+	((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK)
+
+#define OPTEE_SMC_RPC_VAL(func)		((func) | OPTEE_SMC_RETURN_RPC_PREFIX)
+
+/*
+ * Allocate memory for RPC parameter passing. The memory is used to hold a
+ * struct optee_msg_arg.
+ *
+ * "Call" register usage:
+ * a0	This value, OPTEE_SMC_RETURN_RPC_ALLOC
+ * a1	Size in bytes of required argument memory
+ * a2	Not used
+ * a3	Resume information, must be preserved
+ * a4-5	Not used
+ * a6-7	Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0	SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1	Upper 32bits of 64bit physical pointer to allocated
+ *	memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ *	be allocated.
+ * a2	Lower 32bits of 64bit physical pointer to allocated
+ *	memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ *	be allocated
+ * a3	Preserved
+ * a4	Upper 32bits of 64bit Shared memory cookie used when freeing
+ *	the memory or doing an RPC
+ * a5	Lower 32bits of 64bit Shared memory cookie used when freeing
+ *	the memory or doing an RPC
+ * a6-7	Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_ALLOC	0
+#define OPTEE_SMC_RETURN_RPC_ALLOC \
+	OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC)
+
+/*
+ * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC
+ *
+ * "Call" register usage:
+ * a0	This value, OPTEE_SMC_RETURN_RPC_FREE
+ * a1	Upper 32bits of 64bit shared memory cookie belonging to this
+ *	argument memory
+ * a2	Lower 32bits of 64bit shared memory cookie belonging to this
+ *	argument memory
+ * a3-7	Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0	SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-2	Not used
+ * a3-7	Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_FREE		2
+#define OPTEE_SMC_RETURN_RPC_FREE \
+	OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
+
+/*
+ * Deliver foreign interrupt to normal world.
+ *
+ * "Call" register usage:
+ * a0	OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
+ * a1-7	Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0	SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-7	Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR		4
+#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
+	OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
+
+/*
+ * Do an RPC request. The supplied struct optee_msg_arg tells which
+ * request to do and the parameters for the request. The following fields
+ * are used (the rest are unused):
+ * - cmd		the Request ID
+ * - ret		return value of the request, filled in by normal world
+ * - num_params		number of parameters for the request
+ * - params		the parameters
+ * - param_attrs	attributes of the parameters
+ *
+ * "Call" register usage:
+ * a0	OPTEE_SMC_RETURN_RPC_CMD
+ * a1	Upper 32bit of a 64bit Shared memory cookie holding a
+ *	struct optee_msg_arg, must be preserved, only the data should
+ *	be updated
+ * a2	Lower 32bit of a 64bit Shared memory cookie holding a
+ *	struct optee_msg_arg, must be preserved, only the data should
+ *	be updated
+ * a3-7	Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0	SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-2	Not used
+ * a3-7	Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_CMD		5
+#define OPTEE_SMC_RETURN_RPC_CMD \
+	OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
+
+/* Returned in a0 */
+#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
+
+/* Returned in a0 only from Trusted OS functions */
+#define OPTEE_SMC_RETURN_OK		0x0
+#define OPTEE_SMC_RETURN_ETHREAD_LIMIT	0x1
+#define OPTEE_SMC_RETURN_EBUSY		0x2
+#define OPTEE_SMC_RETURN_ERESUME	0x3
+#define OPTEE_SMC_RETURN_EBADADDR	0x4
+#define OPTEE_SMC_RETURN_EBADCMD	0x5
+#define OPTEE_SMC_RETURN_ENOMEM		0x6
+#define OPTEE_SMC_RETURN_ENOTAVAIL	0x7
+#define OPTEE_SMC_RETURN_IS_RPC(ret)	__optee_smc_return_is_rpc((ret))
+
+static inline bool __optee_smc_return_is_rpc(u32 ret)
+{
+	return ret != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION &&
+	       (ret & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==
+			OPTEE_SMC_RETURN_RPC_PREFIX;
+}
+
+#endif /* OPTEE_SMC_H */
diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c
new file mode 100644
index 000000000000..6965055bd1b5
--- /dev/null
+++ b/drivers/tee/optee/supplicant.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <log.h>
+#include <tee.h>
+
+#include "optee_msg.h"
+#include "optee_msg_supplicant.h"
+#include "optee_private.h"
+#include "optee_smc.h"
+
+static void cmd_shm_alloc(struct udevice *dev, struct optee_msg_arg *arg,
+			  void **page_list)
+{
+	struct tee_shm *shm;
+	void *pl;
+	u64 ph_ptr;
+
+	arg->ret_origin = TEE_ORIGIN_COMMS;
+
+	if (arg->num_params != 1 ||
+	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
+		arg->ret = TEE_ERROR_BAD_PARAMETERS;
+		return;
+	}
+
+	shm = __tee_shm_add(dev, 0, NULL, arg->params[0].u.value.b,
+			    TEE_SHM_REGISTER | TEE_SHM_ALLOC);
+	if (!shm) {
+		arg->ret = TEE_ERROR_OUT_OF_MEMORY;
+		return;
+	}
+
+	pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr);
+	if (!pl) {
+		arg->ret = TEE_ERROR_OUT_OF_MEMORY;
+		tee_shm_free(shm);
+		return;
+	}
+
+	*page_list = pl;
+	arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
+			      OPTEE_MSG_ATTR_NONCONTIG;
+	arg->params[0].u.tmem.buf_ptr = ph_ptr;
+	arg->params[0].u.tmem.size = shm->size;
+	arg->params[0].u.tmem.shm_ref = (ulong)shm;
+	arg->ret = TEE_SUCCESS;
+}
+
+static void cmd_shm_free(struct optee_msg_arg *arg)
+{
+	arg->ret_origin = TEE_ORIGIN_COMMS;
+
+	if (arg->num_params != 1 ||
+	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
+		arg->ret = TEE_ERROR_BAD_PARAMETERS;
+		return;
+	}
+
+	tee_shm_free((struct tee_shm *)(ulong)arg->params[0].u.value.b);
+	arg->ret = TEE_SUCCESS;
+}
+
+void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
+		     void **page_list)
+{
+	struct optee_msg_arg *arg = shm_arg->addr;
+
+	switch (arg->cmd) {
+	case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
+		cmd_shm_alloc(dev, arg, page_list);
+		break;
+	case OPTEE_MSG_RPC_CMD_SHM_FREE:
+		cmd_shm_free(arg);
+		break;
+	case OPTEE_MSG_RPC_CMD_FS:
+		debug("OPTEE_MSG_RPC_CMD_FS not implemented\n");
+		arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
+		break;
+	default:
+		arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	arg->ret_origin = TEE_ORIGIN_COMMS;
+}
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 07/10] arm: dt: hikey: Add optee node
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (5 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 06/10] tee: add OP-TEE driver Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-13 15:53 ` [U-Boot] [PATCH 08/10] optee: support routing of rpmb data frames to mmc Jens Wiklander
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Sync with 14e21cb8f811 ("arm64: dt: hikey: Add optee node"
from Linux kernel.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/arm/dts/hi6220-hikey.dts | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/dts/hi6220-hikey.dts b/arch/arm/dts/hi6220-hikey.dts
index 818525197508..24f09257af00 100644
--- a/arch/arm/dts/hi6220-hikey.dts
+++ b/arch/arm/dts/hi6220-hikey.dts
@@ -31,6 +31,13 @@
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x40000000>;
 	};
+
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+	};
 };
 
 &uart2 {
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 08/10] optee: support routing of rpmb data frames to mmc
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (6 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 07/10] arm: dt: hikey: Add optee node Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-16 12:23   ` Igor Opaniuk
  2018-08-13 15:53 ` [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application Jens Wiklander
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Adds support in optee supplicant to route signed (MACed) RPMB frames
from OP-TEE Secure OS to MMC and vice versa to manipulate the RPMB
partition.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 drivers/tee/optee/Makefile        |   1 +
 drivers/tee/optee/core.c          |   8 ++
 drivers/tee/optee/optee_private.h |  31 ++++-
 drivers/tee/optee/rpmb.c          | 184 ++++++++++++++++++++++++++++++
 drivers/tee/optee/supplicant.c    |   3 +
 5 files changed, 226 insertions(+), 1 deletion(-)
 create mode 100644 drivers/tee/optee/rpmb.c

diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index 6148feb474a5..928d3f80027f 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -2,3 +2,4 @@
 
 obj-y += core.o
 obj-y += supplicant.o
+obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index a810f3b965de..5f308a0c6a96 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -280,6 +280,13 @@ static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg)
 			param.a3 = res.a3;
 			handle_rpc(dev, &param, &page_list);
 		} else {
+			/*
+			 * In case we've accessed RPMB to serve an RPC
+			 * request we need to restore the previously
+			 * selected partition as the caller may expect it
+			 * to remain unchanged.
+			 */
+			optee_suppl_rpmb_release(dev);
 			return call_err_to_res(res.a0);
 		}
 	}
@@ -611,4 +618,5 @@ U_BOOT_DRIVER(optee) = {
 	.probe = optee_probe,
 	.ops = &optee_ops,
 	.platdata_auto_alloc_size = sizeof(struct optee_pdata),
+	.priv_auto_alloc_size = sizeof(struct optee_private),
 };
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index daa470f812a9..b76979d21011 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -6,7 +6,36 @@
 #ifndef __OPTEE_PRIVATE_H
 #define __OPTEE_PRIVATE_H
 
+#include <tee.h>
+#include <log.h>
+
+struct optee_private {
+	struct mmc *rpmb_mmc;
+	int rpmb_dev_id;
+	char rpmb_original_part;
+};
+
+struct optee_msg_arg;
+
+void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
+		     void **page_list);
+
+#ifdef CONFIG_SUPPORT_EMMC_RPMB
+void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg);
+void optee_suppl_rpmb_release(struct udevice *dev);
+#else
+static inline void optee_suppl_cmd_rpmb(struct udevice *dev,
+					struct optee_msg_arg *arg)
+{
+	debug("OPTEE_MSG_RPC_CMD_RPMB not implemented\n");
+	arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline void optee_suppl_rpmb_release(struct udevice *dev)
+{
+}
+#endif
+
 void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr);
-void optee_suppl_cmd(struct udevice *dev, void *shm, void **page_list);
 
 #endif /*__OPTEE_PRIVATE_H*/
diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
new file mode 100644
index 000000000000..c1447a5561c2
--- /dev/null
+++ b/drivers/tee/optee/rpmb.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <log.h>
+#include <tee.h>
+#include <mmc.h>
+
+#include "optee_msg.h"
+#include "optee_private.h"
+
+/*
+ * Request and response definitions must be in sync with the secure side of
+ * OP-TEE.
+ */
+
+/* Request */
+struct rpmb_req {
+	u16 cmd;
+#define RPMB_CMD_DATA_REQ      0x00
+#define RPMB_CMD_GET_DEV_INFO  0x01
+	u16 dev_id;
+	u16 block_count;
+	/* Optional data frames (rpmb_data_frame) follow */
+};
+
+#define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))
+
+/* Response to device info request */
+struct rpmb_dev_info {
+	u8 cid[16];
+	u8 rpmb_size_mult;	/* EXT CSD-slice 168: RPMB Size */
+	u8 rel_wr_sec_c;	/* EXT CSD-slice 222: Reliable Write Sector */
+				/*                    Count */
+	u8 ret_code;
+#define RPMB_CMD_GET_DEV_INFO_RET_OK     0x00
+#define RPMB_CMD_GET_DEV_INFO_RET_ERROR  0x01
+};
+
+static void release_mmc(struct optee_private *priv)
+{
+	int rc;
+
+	if (!priv->rpmb_mmc)
+		return;
+
+	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
+				      priv->rpmb_original_part);
+	if (rc)
+		debug("%s: blk_select_hwpart_devnum() failed: %d\n",
+		      __func__, rc);
+
+	priv->rpmb_mmc = NULL;
+}
+
+static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
+{
+	struct mmc *mmc;
+	int rc;
+
+	if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
+		return priv->rpmb_mmc;
+
+	release_mmc(priv);
+
+	mmc = find_mmc_device(dev_id);
+	if (!mmc) {
+		debug("Cannot find RPMB device\n");
+		return NULL;
+	}
+	if (!(mmc->version & MMC_VERSION_MMC)) {
+		debug("Device id %d is not an eMMC device\n", dev_id);
+		return NULL;
+	}
+	if (mmc->version < MMC_VERSION_4_41) {
+		debug("Device id %d: RPMB not supported before version 4.41\n",
+		      dev_id);
+		return NULL;
+	}
+
+#ifdef CONFIG_BLK
+	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
+#else
+	priv->rpmb_original_part = mmc->block_dev.hwpart;
+#endif
+
+	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
+	if (rc) {
+		debug("Device id %d: cannot select RPMB partition: %d\n",
+		      dev_id, rc);
+		return NULL;
+	}
+
+	priv->rpmb_mmc = mmc;
+	priv->rpmb_dev_id = dev_id;
+	return mmc;
+}
+
+static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
+{
+	struct mmc *mmc = find_mmc_device(dev_id);
+
+	if (!mmc)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	if (!mmc->ext_csd)
+		return TEE_ERROR_GENERIC;
+
+	memcpy(info->cid, mmc->cid, sizeof(info->cid));
+	info->rel_wr_sec_c = mmc->ext_csd[222];
+	info->rpmb_size_mult = mmc->ext_csd[168];
+	info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;
+
+	return TEE_SUCCESS;
+}
+
+static u32 rpmb_process_request(struct optee_private *priv, void *req,
+				ulong req_size, void *rsp, ulong rsp_size)
+{
+	struct rpmb_req *sreq = req;
+	struct mmc *mmc;
+
+	if (req_size < sizeof(*sreq))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	switch (sreq->cmd) {
+	case RPMB_CMD_DATA_REQ:
+		mmc = get_mmc(priv, sreq->dev_id);
+		if (!mmc)
+			return TEE_ERROR_ITEM_NOT_FOUND;
+		if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
+					  req_size - sizeof(struct rpmb_req),
+					  rsp, rsp_size))
+			return TEE_ERROR_BAD_PARAMETERS;
+		return TEE_SUCCESS;
+
+	case RPMB_CMD_GET_DEV_INFO:
+		if (req_size != sizeof(struct rpmb_req) ||
+		    rsp_size != sizeof(struct rpmb_dev_info)) {
+			debug("Invalid req/rsp size\n");
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		return rpmb_get_dev_info(sreq->dev_id, rsp);
+
+	default:
+		debug("Unsupported RPMB command: %d\n", sreq->cmd);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+}
+
+void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
+{
+	struct tee_shm *req_shm;
+	struct tee_shm *rsp_shm;
+	void *req_buf;
+	void *rsp_buf;
+	ulong req_size;
+	ulong rsp_size;
+
+	if (arg->num_params != 2 ||
+	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
+	    arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
+		arg->ret = TEE_ERROR_BAD_PARAMETERS;
+		return;
+	}
+
+	req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
+	req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
+	req_size = arg->params[0].u.rmem.size;
+
+	rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
+	rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
+	rsp_size = arg->params[1].u.rmem.size;
+
+	arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
+					rsp_buf, rsp_size);
+}
+
+void optee_suppl_rpmb_release(struct udevice *dev)
+{
+	release_mmc(dev_get_priv(dev));
+}
diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c
index 6965055bd1b5..14cb8717522c 100644
--- a/drivers/tee/optee/supplicant.c
+++ b/drivers/tee/optee/supplicant.c
@@ -81,6 +81,9 @@ void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
 		debug("OPTEE_MSG_RPC_CMD_FS not implemented\n");
 		arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
 		break;
+	case OPTEE_MSG_RPC_CMD_RPMB:
+		optee_suppl_cmd_rpmb(dev, arg);
+		break;
 	default:
 		arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
 	}
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (7 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 08/10] optee: support routing of rpmb data frames to mmc Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-16 12:22   ` Igor Opaniuk
  2018-08-13 15:53 ` [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB Jens Wiklander
  2018-08-23 10:45 ` [U-Boot] [PATCH 00/10] AVB using OP-TEE Simon Glass
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

Adds configuration option OPTEE_TA_AVB and a header file describing the
interface to the AVB trusted application provided by OP-TEE.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 MAINTAINERS                |  1 +
 drivers/tee/optee/Kconfig  | 16 +++++++++++++
 include/tee.h              |  7 ++++++
 include/tee/optee_ta_avb.h | 48 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 72 insertions(+)
 create mode 100644 include/tee/optee_ta_avb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7458c606ee92..cb36c45d74ea 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -576,6 +576,7 @@ M:	Jens Wiklander <jens.wiklander@linaro.org>
 S:	Maintained
 F:	drivers/tee/
 F:	include/tee.h
+F:	include/tee/
 
 UBI
 M:	Kyungmin Park <kmpark@infradead.org>
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index 8f7ebe161111..a5dc08439629 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -5,3 +5,19 @@ config OPTEE
 	help
 	  This implements the OP-TEE Trusted Execution Environment (TEE)
 	  driver.
+
+if OPTEE
+
+menu "OP-TEE options"
+
+config OPTEE_TA_AVB
+	bool "Support AVB TA"
+	default y
+	help
+	  Enables support for the AVB Trusted Application (TA) in OP-TEE.
+	  The TA can support the "avb" subcommands "read_rb", "write"rb"
+	  and "is_unlocked".
+
+endmenu
+
+endif
diff --git a/include/tee.h b/include/tee.h
index c2ac13e34128..3d95d4b3f740 100644
--- a/include/tee.h
+++ b/include/tee.h
@@ -48,6 +48,13 @@
 
 struct tee_driver_ops;
 
+struct tee_optee_ta_uuid {
+	u32 time_low;
+	u16 time_mid;
+	u16 time_hi_and_version;
+	u8 clock_seq_and_node[8];
+};
+
 struct tee_shm {
 	struct udevice *dev;
 	struct list_head link;
diff --git a/include/tee/optee_ta_avb.h b/include/tee/optee_ta_avb.h
new file mode 100644
index 000000000000..0e1da084e09d
--- /dev/null
+++ b/include/tee/optee_ta_avb.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/* Copyright (c) 2018, Linaro Limited */
+
+#ifndef __TA_AVB_H
+#define __TA_AVB_H
+
+#define TA_AVB_UUID { 0x023f8f1a, 0x292a, 0x432b, \
+		      { 0x8f, 0xc4, 0xde, 0x84, 0x71, 0x35, 0x80, 0x67 } }
+
+#define TA_AVB_MAX_ROLLBACK_LOCATIONS	256
+
+/*
+ * Gets the rollback index corresponding to the given rollback index slot.
+ *
+ * in	params[0].value.a:	rollback index slot
+ * out	params[1].value.a:	upper 32 bits of rollback index
+ * out	params[1].value.b:	lower 32 bits of rollback index
+ */
+#define TA_AVB_CMD_READ_ROLLBACK_INDEX	0
+
+/*
+ * Updates the rollback index corresponding to the given rollback index slot.
+ *
+ * Will refuse to update a slot with a lower value.
+ *
+ * in	params[0].value.a:	rollback index slot
+ * in	params[1].value.a:	upper 32 bits of rollback index
+ * in	params[1].value.b:	lower 32 bits of rollback index
+ */
+#define TA_AVB_CMD_WRITE_ROLLBACK_INDEX	1
+
+/*
+ * Gets the lock state of the device.
+ *
+ * out	params[0].value.a:	lock state
+ */
+#define TA_AVB_CMD_READ_LOCK_STATE	2
+
+/*
+ * Sets the lock state of the device.
+ *
+ * If the lock state is changed all rollback slots will be reset to 0
+ *
+ * in	params[0].value.a:	lock state
+ */
+#define TA_AVB_CMD_WRITE_LOCK_STATE	3
+
+#endif /*__TA_AVB_H*/
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (8 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application Jens Wiklander
@ 2018-08-13 15:53 ` Jens Wiklander
  2018-08-14 11:20   ` Igor Opaniuk
  2018-08-23 10:45 ` [U-Boot] [PATCH 00/10] AVB using OP-TEE Simon Glass
  10 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-13 15:53 UTC (permalink / raw)
  To: u-boot

With CONFIG_OPTEE_TA_AVB use the trusted application AVB provided by
OP-TEE to manage rollback indexes and device lock status.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 common/avb_verify.c  | 132 ++++++++++++++++++++++++++++++++++++++++++-
 include/avb_verify.h |   4 ++
 2 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/common/avb_verify.c b/common/avb_verify.c
index 20e35ade3029..a50c05bf7847 100644
--- a/common/avb_verify.c
+++ b/common/avb_verify.c
@@ -10,6 +10,8 @@
 #include <image.h>
 #include <malloc.h>
 #include <part.h>
+#include <tee.h>
+#include <tee/optee_ta_avb.h>
 
 const unsigned char avb_root_pub[1032] = {
 	0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
@@ -594,6 +596,79 @@ static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
 	return AVB_IO_RESULT_OK;
 }
 
+#ifdef CONFIG_OPTEE_TA_AVB
+static void uuid_to_octets(u8 d[TEE_UUID_LEN],
+			   const struct tee_optee_ta_uuid *s)
+{
+	d[0] = s->time_low >> 24;
+	d[1] = s->time_low >> 16;
+	d[2] = s->time_low >> 8;
+	d[3] = s->time_low;
+	d[4] = s->time_mid >> 8;
+	d[5] = s->time_mid;
+	d[6] = s->time_hi_and_version >> 8;
+	d[7] = s->time_hi_and_version;
+	memcpy(d + 8, s->clock_seq_and_node, sizeof(s->clock_seq_and_node));
+}
+
+static int get_open_session(struct AvbOpsData *ops_data)
+{
+	struct udevice *tee = NULL;
+
+	while (!ops_data->tee) {
+		const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
+		struct tee_open_session_arg arg;
+		int rc;
+
+		tee = tee_find_device(tee, NULL, NULL, NULL);
+		if (!tee)
+			return -ENODEV;
+
+		memset(&arg, 0, sizeof(arg));
+		uuid_to_octets(arg.uuid, &uuid);
+		rc = tee_open_session(tee, &arg, 0, NULL);
+		if (!rc) {
+			ops_data->tee = tee;
+			ops_data->session = arg.session;
+		}
+	}
+
+	return 0;
+}
+
+static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
+			       ulong num_param, struct tee_param *param)
+{
+	struct tee_invoke_arg arg;
+
+	if (get_open_session(ops_data))
+		return AVB_IO_RESULT_ERROR_IO;
+
+	memset(&arg, 0, sizeof(arg));
+	arg.func = func;
+	arg.session = ops_data->session;
+
+	if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
+		return AVB_IO_RESULT_ERROR_IO;
+	switch (arg.ret) {
+	case TEE_SUCCESS:
+		return AVB_IO_RESULT_OK;
+	case TEE_ERROR_OUT_OF_MEMORY:
+		return AVB_IO_RESULT_ERROR_OOM;
+	case TEE_ERROR_TARGET_DEAD:
+		/*
+		 * The TA has paniced, close the session to reload the TA
+		 * for the next request.
+		 */
+		tee_close_session(ops_data->tee, ops_data->session);
+		ops_data->tee = NULL;
+		return AVB_IO_RESULT_ERROR_IO;
+	default:
+		return AVB_IO_RESULT_ERROR_IO;
+	}
+}
+#endif
+
 /**
  * read_rollback_index() - gets the rollback index corresponding to the
  * location of given by @out_rollback_index.
@@ -609,6 +684,7 @@ static AvbIOResult read_rollback_index(AvbOps *ops,
 				       size_t rollback_index_slot,
 				       u64 *out_rollback_index)
 {
+#ifndef CONFIG_OPTEE_TA_AVB
 	/* For now we always return 0 as the stored rollback index. */
 	printf("%s not supported yet\n", __func__);
 
@@ -616,6 +692,27 @@ static AvbIOResult read_rollback_index(AvbOps *ops,
 		*out_rollback_index = 0;
 
 	return AVB_IO_RESULT_OK;
+#else
+	AvbIOResult rc;
+	struct tee_param param[2];
+
+	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
+		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
+
+	memset(param, 0, sizeof(param));
+	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+	param[0].u.value.a = rollback_index_slot;
+	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
+
+	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
+			 ARRAY_SIZE(param), param);
+	if (rc)
+		return rc;
+
+	*out_rollback_index = (u64)param[1].u.value.a << 32 |
+			      (u32)param[1].u.value.b;
+	return AVB_IO_RESULT_OK;
+#endif
 }
 
 /**
@@ -633,10 +730,27 @@ static AvbIOResult write_rollback_index(AvbOps *ops,
 					size_t rollback_index_slot,
 					u64 rollback_index)
 {
+#ifndef CONFIG_OPTEE_TA_AVB
 	/* For now this is a no-op. */
 	printf("%s not supported yet\n", __func__);
 
 	return AVB_IO_RESULT_OK;
+#else
+	struct tee_param param[2];
+
+	if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
+		return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
+
+	memset(param, 0, sizeof(param));
+	param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+	param[0].u.value.a = rollback_index_slot;
+	param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+	param[1].u.value.a = (u32)(rollback_index >> 32);
+	param[1].u.value.b = (u32)rollback_index;
+
+	return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
+			   ARRAY_SIZE(param), param);
+#endif
 }
 
 /**
@@ -652,6 +766,7 @@ static AvbIOResult write_rollback_index(AvbOps *ops,
  */
 static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
 {
+#ifndef CONFIG_OPTEE_TA_AVB
 	/* For now we always return that the device is unlocked. */
 
 	printf("%s not supported yet\n", __func__);
@@ -659,6 +774,16 @@ static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
 	*out_is_unlocked = true;
 
 	return AVB_IO_RESULT_OK;
+#else
+	AvbIOResult rc;
+	struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
+
+	rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
+	if (rc)
+		return rc;
+	*out_is_unlocked = !param.u.value.a;
+	return AVB_IO_RESULT_OK;
+#endif
 }
 
 /**
@@ -737,6 +862,11 @@ void avb_ops_free(AvbOps *ops)
 
 	ops_data = ops->user_data;
 
-	if (ops_data)
+	if (ops_data) {
+#ifdef CONFIG_OPTEE_TA_AVB
+		if (ops_data->tee)
+			tee_close_session(ops_data->tee, ops_data->session);
+#endif
 		avb_free(ops_data);
+	}
 }
diff --git a/include/avb_verify.h b/include/avb_verify.h
index eaa60f5393ef..a532a2331aea 100644
--- a/include/avb_verify.h
+++ b/include/avb_verify.h
@@ -27,6 +27,10 @@ struct AvbOpsData {
 	struct AvbOps ops;
 	int mmc_dev;
 	enum avb_boot_state boot_state;
+#ifdef CONFIG_OPTEE_TA_AVB
+	struct udevice *tee;
+	u32 session;
+#endif
 };
 
 struct mmc_part {
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB
  2018-08-13 15:53 ` [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB Jens Wiklander
@ 2018-08-14 11:20   ` Igor Opaniuk
  2018-08-16 12:17     ` Igor Opaniuk
  0 siblings, 1 reply; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-14 11:20 UTC (permalink / raw)
  To: u-boot

Hi Jens,

Could you please also add info about CONFIG_OPTEE_TA_AVB to the
existing doc/README.avb2 and more description of
how/where rollback indexes/device lock state are stored (this what you
explained in the cover letter for this patchset).

Thanks

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> With CONFIG_OPTEE_TA_AVB use the trusted application AVB provided by
> OP-TEE to manage rollback indexes and device lock status.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  common/avb_verify.c  | 132 ++++++++++++++++++++++++++++++++++++++++++-
>  include/avb_verify.h |   4 ++
>  2 files changed, 135 insertions(+), 1 deletion(-)
>
> diff --git a/common/avb_verify.c b/common/avb_verify.c
> index 20e35ade3029..a50c05bf7847 100644
> --- a/common/avb_verify.c
> +++ b/common/avb_verify.c
> @@ -10,6 +10,8 @@
>  #include <image.h>
>  #include <malloc.h>
>  #include <part.h>
> +#include <tee.h>
> +#include <tee/optee_ta_avb.h>
>
>  const unsigned char avb_root_pub[1032] = {
>         0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
> @@ -594,6 +596,79 @@ static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
>         return AVB_IO_RESULT_OK;
>  }
>
> +#ifdef CONFIG_OPTEE_TA_AVB
> +static void uuid_to_octets(u8 d[TEE_UUID_LEN],
> +                          const struct tee_optee_ta_uuid *s)
> +{
> +       d[0] = s->time_low >> 24;
> +       d[1] = s->time_low >> 16;
> +       d[2] = s->time_low >> 8;
> +       d[3] = s->time_low;
> +       d[4] = s->time_mid >> 8;
> +       d[5] = s->time_mid;
> +       d[6] = s->time_hi_and_version >> 8;
> +       d[7] = s->time_hi_and_version;
> +       memcpy(d + 8, s->clock_seq_and_node, sizeof(s->clock_seq_and_node));
> +}
> +
> +static int get_open_session(struct AvbOpsData *ops_data)
> +{
> +       struct udevice *tee = NULL;
> +
> +       while (!ops_data->tee) {
> +               const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
> +               struct tee_open_session_arg arg;
> +               int rc;
> +
> +               tee = tee_find_device(tee, NULL, NULL, NULL);
> +               if (!tee)
> +                       return -ENODEV;
> +
> +               memset(&arg, 0, sizeof(arg));
> +               uuid_to_octets(arg.uuid, &uuid);
> +               rc = tee_open_session(tee, &arg, 0, NULL);
> +               if (!rc) {
> +                       ops_data->tee = tee;
> +                       ops_data->session = arg.session;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
> +                              ulong num_param, struct tee_param *param)
> +{
> +       struct tee_invoke_arg arg;
> +
> +       if (get_open_session(ops_data))
> +               return AVB_IO_RESULT_ERROR_IO;
> +
> +       memset(&arg, 0, sizeof(arg));
> +       arg.func = func;
> +       arg.session = ops_data->session;
> +
> +       if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
> +               return AVB_IO_RESULT_ERROR_IO;
> +       switch (arg.ret) {
> +       case TEE_SUCCESS:
> +               return AVB_IO_RESULT_OK;
> +       case TEE_ERROR_OUT_OF_MEMORY:
> +               return AVB_IO_RESULT_ERROR_OOM;
> +       case TEE_ERROR_TARGET_DEAD:
> +               /*
> +                * The TA has paniced, close the session to reload the TA
> +                * for the next request.
> +                */
> +               tee_close_session(ops_data->tee, ops_data->session);
> +               ops_data->tee = NULL;
> +               return AVB_IO_RESULT_ERROR_IO;
> +       default:
> +               return AVB_IO_RESULT_ERROR_IO;
> +       }
> +}
> +#endif
> +
>  /**
>   * read_rollback_index() - gets the rollback index corresponding to the
>   * location of given by @out_rollback_index.
> @@ -609,6 +684,7 @@ static AvbIOResult read_rollback_index(AvbOps *ops,
>                                        size_t rollback_index_slot,
>                                        u64 *out_rollback_index)
>  {
> +#ifndef CONFIG_OPTEE_TA_AVB
>         /* For now we always return 0 as the stored rollback index. */
>         printf("%s not supported yet\n", __func__);
>
> @@ -616,6 +692,27 @@ static AvbIOResult read_rollback_index(AvbOps *ops,
>                 *out_rollback_index = 0;
>
>         return AVB_IO_RESULT_OK;
> +#else
> +       AvbIOResult rc;
> +       struct tee_param param[2];
> +
> +       if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
> +               return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
> +
> +       memset(param, 0, sizeof(param));
> +       param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
> +       param[0].u.value.a = rollback_index_slot;
> +       param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
> +
> +       rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
> +                        ARRAY_SIZE(param), param);
> +       if (rc)
> +               return rc;
> +
> +       *out_rollback_index = (u64)param[1].u.value.a << 32 |
> +                             (u32)param[1].u.value.b;
> +       return AVB_IO_RESULT_OK;
> +#endif
>  }
>
>  /**
> @@ -633,10 +730,27 @@ static AvbIOResult write_rollback_index(AvbOps *ops,
>                                         size_t rollback_index_slot,
>                                         u64 rollback_index)
>  {
> +#ifndef CONFIG_OPTEE_TA_AVB
>         /* For now this is a no-op. */
>         printf("%s not supported yet\n", __func__);
>
>         return AVB_IO_RESULT_OK;
> +#else
> +       struct tee_param param[2];
> +
> +       if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
> +               return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
> +
> +       memset(param, 0, sizeof(param));
> +       param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
> +       param[0].u.value.a = rollback_index_slot;
> +       param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
> +       param[1].u.value.a = (u32)(rollback_index >> 32);
> +       param[1].u.value.b = (u32)rollback_index;
> +
> +       return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
> +                          ARRAY_SIZE(param), param);
> +#endif
>  }
>
>  /**
> @@ -652,6 +766,7 @@ static AvbIOResult write_rollback_index(AvbOps *ops,
>   */
>  static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
>  {
> +#ifndef CONFIG_OPTEE_TA_AVB
>         /* For now we always return that the device is unlocked. */
>
>         printf("%s not supported yet\n", __func__);
> @@ -659,6 +774,16 @@ static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
>         *out_is_unlocked = true;
>
>         return AVB_IO_RESULT_OK;
> +#else
> +       AvbIOResult rc;
> +       struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
> +
> +       rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
> +       if (rc)
> +               return rc;
> +       *out_is_unlocked = !param.u.value.a;
> +       return AVB_IO_RESULT_OK;
> +#endif
>  }
>
>  /**
> @@ -737,6 +862,11 @@ void avb_ops_free(AvbOps *ops)
>
>         ops_data = ops->user_data;
>
> -       if (ops_data)
> +       if (ops_data) {
> +#ifdef CONFIG_OPTEE_TA_AVB
> +               if (ops_data->tee)
> +                       tee_close_session(ops_data->tee, ops_data->session);
> +#endif
>                 avb_free(ops_data);
> +       }
>  }
> diff --git a/include/avb_verify.h b/include/avb_verify.h
> index eaa60f5393ef..a532a2331aea 100644
> --- a/include/avb_verify.h
> +++ b/include/avb_verify.h
> @@ -27,6 +27,10 @@ struct AvbOpsData {
>         struct AvbOps ops;
>         int mmc_dev;
>         enum avb_boot_state boot_state;
> +#ifdef CONFIG_OPTEE_TA_AVB
> +       struct udevice *tee;
> +       u32 session;
> +#endif
>  };
>
>  struct mmc_part {
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 02/10] cmd: avb read_rb: print rb_idx in hexadecimal
  2018-08-13 15:53 ` [U-Boot] [PATCH 02/10] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
@ 2018-08-14 11:34   ` Igor Opaniuk
  0 siblings, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-14 11:34 UTC (permalink / raw)
  To: u-boot

Typo in the commit message "hexadeciaml number", otherwise:

Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Prior to this patch was do_avb_write_rb() reading supplied rb_idx as a
> hexadecimal number while do_avb_read_rb() printed the read out rb_idx as
> decimal number. For consistency change do_avb_read_rb() to print rb_idx
> as a hexadeciaml number too.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  cmd/avb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/cmd/avb.c b/cmd/avb.c
> index f045a0c64c4a..ca4b26d5d7b3 100644
> --- a/cmd/avb.c
> +++ b/cmd/avb.c
> @@ -158,7 +158,7 @@ int do_avb_read_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>
>         if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) ==
>             AVB_IO_RESULT_OK) {
> -               printf("Rollback index: %llu\n", rb_idx);
> +               printf("Rollback index: %llx\n", rb_idx);
>                 return CMD_RET_SUCCESS;
>         }
>         return CMD_RET_FAILURE;
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-13 15:53 ` [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too Jens Wiklander
@ 2018-08-15 14:17   ` Tom Rini
  2018-08-15 14:30     ` Michal Simek
  0 siblings, 1 reply; 40+ messages in thread
From: Tom Rini @ 2018-08-15 14:17 UTC (permalink / raw)
  To: u-boot

On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:

> Just as /chosen may contain devices /firmware may contain devices, scan
> for devices under /firmware too.
> 
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  drivers/core/root.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/core/root.c b/drivers/core/root.c
> index 72bcc7d7f2a3..0dca507e1187 100644
> --- a/drivers/core/root.c
> +++ b/drivers/core/root.c
> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
>  	for (offset = fdt_first_subnode(blob, offset);
>  	     offset > 0;
>  	     offset = fdt_next_subnode(blob, offset)) {
> -		/* "chosen" node isn't a device itself but may contain some: */
> -		if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
> -			pr_debug("parsing subnodes of \"chosen\"\n");
> +		const char *node_name = fdt_get_name(blob, offset, NULL);
> +
> +		/*
> +		 * The "chosen" and "firmware" nodes aren't devices
> +		 * themselves but may contain some:
> +		 */
> +		if (!strcmp(node_name, "chosen") ||
> +		    !strcmp(node_name, "firmware")) {
> +			pr_debug("parsing subnodes of \"%s\"\n", node_name);
>  
>  			err = dm_scan_fdt_node(parent, blob, offset,
>  					       pre_reloc_only);

So, the /firmware node seems special.  Have you talked with the
devicetree folks to get it listed in the spec?  That would seem rather
valuable for something used by many parties.  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180815/bc0d37ab/attachment.sig>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-15 14:17   ` Tom Rini
@ 2018-08-15 14:30     ` Michal Simek
  2018-08-15 14:34       ` Tom Rini
  0 siblings, 1 reply; 40+ messages in thread
From: Michal Simek @ 2018-08-15 14:30 UTC (permalink / raw)
  To: u-boot

On 15.8.2018 16:17, Tom Rini wrote:
> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
> 
>> Just as /chosen may contain devices /firmware may contain devices, scan
>> for devices under /firmware too.
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  drivers/core/root.c | 15 ++++++++++-----
>>  1 file changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/core/root.c b/drivers/core/root.c
>> index 72bcc7d7f2a3..0dca507e1187 100644
>> --- a/drivers/core/root.c
>> +++ b/drivers/core/root.c
>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
>>  	for (offset = fdt_first_subnode(blob, offset);
>>  	     offset > 0;
>>  	     offset = fdt_next_subnode(blob, offset)) {
>> -		/* "chosen" node isn't a device itself but may contain some: */
>> -		if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
>> -			pr_debug("parsing subnodes of \"chosen\"\n");
>> +		const char *node_name = fdt_get_name(blob, offset, NULL);
>> +
>> +		/*
>> +		 * The "chosen" and "firmware" nodes aren't devices
>> +		 * themselves but may contain some:
>> +		 */
>> +		if (!strcmp(node_name, "chosen") ||
>> +		    !strcmp(node_name, "firmware")) {
>> +			pr_debug("parsing subnodes of \"%s\"\n", node_name);
>>  
>>  			err = dm_scan_fdt_node(parent, blob, offset,
>>  					       pre_reloc_only);
> 
> So, the /firmware node seems special.  Have you talked with the
> devicetree folks to get it listed in the spec?  That would seem rather
> valuable for something used by many parties.  Thanks!
> 

some days ago we have sent a patch for this too.
https://lists.denx.de/pipermail/u-boot/2018-August/338049.html

It is using different way but it should do the same thing.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-15 14:30     ` Michal Simek
@ 2018-08-15 14:34       ` Tom Rini
  2018-08-15 14:50           ` Michal Simek
  0 siblings, 1 reply; 40+ messages in thread
From: Tom Rini @ 2018-08-15 14:34 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
> On 15.8.2018 16:17, Tom Rini wrote:
> > On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
> > 
> >> Just as /chosen may contain devices /firmware may contain devices, scan
> >> for devices under /firmware too.
> >>
> >> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> >> ---
> >>  drivers/core/root.c | 15 ++++++++++-----
> >>  1 file changed, 10 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/core/root.c b/drivers/core/root.c
> >> index 72bcc7d7f2a3..0dca507e1187 100644
> >> --- a/drivers/core/root.c
> >> +++ b/drivers/core/root.c
> >> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
> >>  	for (offset = fdt_first_subnode(blob, offset);
> >>  	     offset > 0;
> >>  	     offset = fdt_next_subnode(blob, offset)) {
> >> -		/* "chosen" node isn't a device itself but may contain some: */
> >> -		if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
> >> -			pr_debug("parsing subnodes of \"chosen\"\n");
> >> +		const char *node_name = fdt_get_name(blob, offset, NULL);
> >> +
> >> +		/*
> >> +		 * The "chosen" and "firmware" nodes aren't devices
> >> +		 * themselves but may contain some:
> >> +		 */
> >> +		if (!strcmp(node_name, "chosen") ||
> >> +		    !strcmp(node_name, "firmware")) {
> >> +			pr_debug("parsing subnodes of \"%s\"\n", node_name);
> >>  
> >>  			err = dm_scan_fdt_node(parent, blob, offset,
> >>  					       pre_reloc_only);
> > 
> > So, the /firmware node seems special.  Have you talked with the
> > devicetree folks to get it listed in the spec?  That would seem rather
> > valuable for something used by many parties.  Thanks!
> > 
> 
> some days ago we have sent a patch for this too.
> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
> 
> It is using different way but it should do the same thing.

OK, so it sounds like in terms of code clean-ups, we need something like
what you reference and then some further clean-ups on top of that
perhaps for other places to call dm_scan_fdt_ofnode_path() for special
cases.  And in terms of formalized specification bits, I do think
/firmware should perhaps get kicked up to the spec itself so that it's
very clear to all consumers.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180815/dce2cc62/attachment.sig>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-15 14:34       ` Tom Rini
@ 2018-08-15 14:50           ` Michal Simek
  0 siblings, 0 replies; 40+ messages in thread
From: Michal Simek @ 2018-08-15 14:50 UTC (permalink / raw)
  To: u-boot

Hi Rob,

On 15.8.2018 16:34, Tom Rini wrote:
> On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
>> On 15.8.2018 16:17, Tom Rini wrote:
>>> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
>>>
>>>> Just as /chosen may contain devices /firmware may contain devices, scan
>>>> for devices under /firmware too.
>>>>
>>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>>>> ---
>>>>  drivers/core/root.c | 15 ++++++++++-----
>>>>  1 file changed, 10 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/core/root.c b/drivers/core/root.c
>>>> index 72bcc7d7f2a3..0dca507e1187 100644
>>>> --- a/drivers/core/root.c
>>>> +++ b/drivers/core/root.c
>>>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
>>>>  	for (offset = fdt_first_subnode(blob, offset);
>>>>  	     offset > 0;
>>>>  	     offset = fdt_next_subnode(blob, offset)) {
>>>> -		/* "chosen" node isn't a device itself but may contain some: */
>>>> -		if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
>>>> -			pr_debug("parsing subnodes of \"chosen\"\n");
>>>> +		const char *node_name = fdt_get_name(blob, offset, NULL);
>>>> +
>>>> +		/*
>>>> +		 * The "chosen" and "firmware" nodes aren't devices
>>>> +		 * themselves but may contain some:
>>>> +		 */
>>>> +		if (!strcmp(node_name, "chosen") ||
>>>> +		    !strcmp(node_name, "firmware")) {
>>>> +			pr_debug("parsing subnodes of \"%s\"\n", node_name);
>>>>  
>>>>  			err = dm_scan_fdt_node(parent, blob, offset,
>>>>  					       pre_reloc_only);
>>>
>>> So, the /firmware node seems special.  Have you talked with the
>>> devicetree folks to get it listed in the spec?  That would seem rather
>>> valuable for something used by many parties.  Thanks!
>>>
>>
>> some days ago we have sent a patch for this too.
>> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
>>
>> It is using different way but it should do the same thing.
> 
> OK, so it sounds like in terms of code clean-ups, we need something like
> what you reference and then some further clean-ups on top of that
> perhaps for other places to call dm_scan_fdt_ofnode_path() for special
> cases.  And in terms of formalized specification bits, I do think
> /firmware should perhaps get kicked up to the spec itself so that it's
> very clear to all consumers.

I was also checking latest devicetree spec and there is no record about
/firmware node and how it is supposed to be used.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 01/10] dm: fdt: scan for devices under /firmware too
@ 2018-08-15 14:50           ` Michal Simek
  0 siblings, 0 replies; 40+ messages in thread
From: Michal Simek @ 2018-08-15 14:50 UTC (permalink / raw)
  To: Tom Rini, Michal Simek, Rob Herring
  Cc: devicetree-spec, u-boot, Pierre Aubert

Hi Rob,

On 15.8.2018 16:34, Tom Rini wrote:
> On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
>> On 15.8.2018 16:17, Tom Rini wrote:
>>> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
>>>
>>>> Just as /chosen may contain devices /firmware may contain devices, scan
>>>> for devices under /firmware too.
>>>>
>>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>>>> ---
>>>>  drivers/core/root.c | 15 ++++++++++-----
>>>>  1 file changed, 10 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/core/root.c b/drivers/core/root.c
>>>> index 72bcc7d7f2a3..0dca507e1187 100644
>>>> --- a/drivers/core/root.c
>>>> +++ b/drivers/core/root.c
>>>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
>>>>  	for (offset = fdt_first_subnode(blob, offset);
>>>>  	     offset > 0;
>>>>  	     offset = fdt_next_subnode(blob, offset)) {
>>>> -		/* "chosen" node isn't a device itself but may contain some: */
>>>> -		if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
>>>> -			pr_debug("parsing subnodes of \"chosen\"\n");
>>>> +		const char *node_name = fdt_get_name(blob, offset, NULL);
>>>> +
>>>> +		/*
>>>> +		 * The "chosen" and "firmware" nodes aren't devices
>>>> +		 * themselves but may contain some:
>>>> +		 */
>>>> +		if (!strcmp(node_name, "chosen") ||
>>>> +		    !strcmp(node_name, "firmware")) {
>>>> +			pr_debug("parsing subnodes of \"%s\"\n", node_name);
>>>>  
>>>>  			err = dm_scan_fdt_node(parent, blob, offset,
>>>>  					       pre_reloc_only);
>>>
>>> So, the /firmware node seems special.  Have you talked with the
>>> devicetree folks to get it listed in the spec?  That would seem rather
>>> valuable for something used by many parties.  Thanks!
>>>
>>
>> some days ago we have sent a patch for this too.
>> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
>>
>> It is using different way but it should do the same thing.
> 
> OK, so it sounds like in terms of code clean-ups, we need something like
> what you reference and then some further clean-ups on top of that
> perhaps for other places to call dm_scan_fdt_ofnode_path() for special
> cases.  And in terms of formalized specification bits, I do think
> /firmware should perhaps get kicked up to the spec itself so that it's
> very clear to all consumers.

I was also checking latest devicetree spec and there is no record about
/firmware node and how it is supposed to be used.

Thanks,
Michal
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-15 14:50           ` Michal Simek
@ 2018-08-15 15:31             ` Rob Herring
  -1 siblings, 0 replies; 40+ messages in thread
From: Rob Herring @ 2018-08-15 15:31 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 15, 2018 at 8:51 AM Michal Simek <michal.simek@xilinx.com> wrote:
>
> Hi Rob,
>
> On 15.8.2018 16:34, Tom Rini wrote:
> > On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
> >> On 15.8.2018 16:17, Tom Rini wrote:
> >>> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
> >>>
> >>>> Just as /chosen may contain devices /firmware may contain devices, scan
> >>>> for devices under /firmware too.
> >>>>
> >>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> >>>> ---
> >>>>  drivers/core/root.c | 15 ++++++++++-----
> >>>>  1 file changed, 10 insertions(+), 5 deletions(-)
> >>>>
> >>>> diff --git a/drivers/core/root.c b/drivers/core/root.c
> >>>> index 72bcc7d7f2a3..0dca507e1187 100644
> >>>> --- a/drivers/core/root.c
> >>>> +++ b/drivers/core/root.c
> >>>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
> >>>>    for (offset = fdt_first_subnode(blob, offset);
> >>>>         offset > 0;
> >>>>         offset = fdt_next_subnode(blob, offset)) {
> >>>> -          /* "chosen" node isn't a device itself but may contain some: */
> >>>> -          if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
> >>>> -                  pr_debug("parsing subnodes of \"chosen\"\n");
> >>>> +          const char *node_name = fdt_get_name(blob, offset, NULL);
> >>>> +
> >>>> +          /*
> >>>> +           * The "chosen" and "firmware" nodes aren't devices
> >>>> +           * themselves but may contain some:
> >>>> +           */
> >>>> +          if (!strcmp(node_name, "chosen") ||
> >>>> +              !strcmp(node_name, "firmware")) {
> >>>> +                  pr_debug("parsing subnodes of \"%s\"\n", node_name);
> >>>>
> >>>>                    err = dm_scan_fdt_node(parent, blob, offset,
> >>>>                                           pre_reloc_only);
> >>>
> >>> So, the /firmware node seems special.  Have you talked with the
> >>> devicetree folks to get it listed in the spec?  That would seem rather
> >>> valuable for something used by many parties.  Thanks!
> >>>
> >>
> >> some days ago we have sent a patch for this too.
> >> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
> >>
> >> It is using different way but it should do the same thing.
> >
> > OK, so it sounds like in terms of code clean-ups, we need something like
> > what you reference and then some further clean-ups on top of that
> > perhaps for other places to call dm_scan_fdt_ofnode_path() for special
> > cases.  And in terms of formalized specification bits, I do think
> > /firmware should perhaps get kicked up to the spec itself so that it's
> > very clear to all consumers.
>
> I was also checking latest devicetree spec and there is no record about
> /firmware node and how it is supposed to be used.

Patches welcome. :)

It's really only a container to define non-discoverable firmware
interfaces. Typically accessed thru a secure call (for ARM) or a
mailbox. It is primarily just convention rather than a strict
requirement. We have to support firmware nodes at the top-level too
anyways.

Rob

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 01/10] dm: fdt: scan for devices under /firmware too
@ 2018-08-15 15:31             ` Rob Herring
  0 siblings, 0 replies; 40+ messages in thread
From: Rob Herring @ 2018-08-15 15:31 UTC (permalink / raw)
  To: Michal Simek; +Cc: devicetree-spec, Tom Rini, p.aubert, U-Boot Mailing List

On Wed, Aug 15, 2018 at 8:51 AM Michal Simek <michal.simek@xilinx.com> wrote:
>
> Hi Rob,
>
> On 15.8.2018 16:34, Tom Rini wrote:
> > On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
> >> On 15.8.2018 16:17, Tom Rini wrote:
> >>> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
> >>>
> >>>> Just as /chosen may contain devices /firmware may contain devices, scan
> >>>> for devices under /firmware too.
> >>>>
> >>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> >>>> ---
> >>>>  drivers/core/root.c | 15 ++++++++++-----
> >>>>  1 file changed, 10 insertions(+), 5 deletions(-)
> >>>>
> >>>> diff --git a/drivers/core/root.c b/drivers/core/root.c
> >>>> index 72bcc7d7f2a3..0dca507e1187 100644
> >>>> --- a/drivers/core/root.c
> >>>> +++ b/drivers/core/root.c
> >>>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
> >>>>    for (offset = fdt_first_subnode(blob, offset);
> >>>>         offset > 0;
> >>>>         offset = fdt_next_subnode(blob, offset)) {
> >>>> -          /* "chosen" node isn't a device itself but may contain some: */
> >>>> -          if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
> >>>> -                  pr_debug("parsing subnodes of \"chosen\"\n");
> >>>> +          const char *node_name = fdt_get_name(blob, offset, NULL);
> >>>> +
> >>>> +          /*
> >>>> +           * The "chosen" and "firmware" nodes aren't devices
> >>>> +           * themselves but may contain some:
> >>>> +           */
> >>>> +          if (!strcmp(node_name, "chosen") ||
> >>>> +              !strcmp(node_name, "firmware")) {
> >>>> +                  pr_debug("parsing subnodes of \"%s\"\n", node_name);
> >>>>
> >>>>                    err = dm_scan_fdt_node(parent, blob, offset,
> >>>>                                           pre_reloc_only);
> >>>
> >>> So, the /firmware node seems special.  Have you talked with the
> >>> devicetree folks to get it listed in the spec?  That would seem rather
> >>> valuable for something used by many parties.  Thanks!
> >>>
> >>
> >> some days ago we have sent a patch for this too.
> >> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
> >>
> >> It is using different way but it should do the same thing.
> >
> > OK, so it sounds like in terms of code clean-ups, we need something like
> > what you reference and then some further clean-ups on top of that
> > perhaps for other places to call dm_scan_fdt_ofnode_path() for special
> > cases.  And in terms of formalized specification bits, I do think
> > /firmware should perhaps get kicked up to the spec itself so that it's
> > very clear to all consumers.
>
> I was also checking latest devicetree spec and there is no record about
> /firmware node and how it is supposed to be used.

Patches welcome. :)

It's really only a container to define non-discoverable firmware
interfaces. Typically accessed thru a secure call (for ARM) or a
mailbox. It is primarily just convention rather than a strict
requirement. We have to support firmware nodes at the top-level too
anyways.

Rob
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too
  2018-08-15 15:31             ` Rob Herring
@ 2018-08-15 15:43               ` Tom Rini
  -1 siblings, 0 replies; 40+ messages in thread
From: Tom Rini @ 2018-08-15 15:43 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 15, 2018 at 09:31:30AM -0600, Rob Herring wrote:
> On Wed, Aug 15, 2018 at 8:51 AM Michal Simek <michal.simek@xilinx.com> wrote:
> >
> > Hi Rob,
> >
> > On 15.8.2018 16:34, Tom Rini wrote:
> > > On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
> > >> On 15.8.2018 16:17, Tom Rini wrote:
> > >>> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
> > >>>
> > >>>> Just as /chosen may contain devices /firmware may contain devices, scan
> > >>>> for devices under /firmware too.
> > >>>>
> > >>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> > >>>> ---
> > >>>>  drivers/core/root.c | 15 ++++++++++-----
> > >>>>  1 file changed, 10 insertions(+), 5 deletions(-)
> > >>>>
> > >>>> diff --git a/drivers/core/root.c b/drivers/core/root.c
> > >>>> index 72bcc7d7f2a3..0dca507e1187 100644
> > >>>> --- a/drivers/core/root.c
> > >>>> +++ b/drivers/core/root.c
> > >>>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
> > >>>>    for (offset = fdt_first_subnode(blob, offset);
> > >>>>         offset > 0;
> > >>>>         offset = fdt_next_subnode(blob, offset)) {
> > >>>> -          /* "chosen" node isn't a device itself but may contain some: */
> > >>>> -          if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
> > >>>> -                  pr_debug("parsing subnodes of \"chosen\"\n");
> > >>>> +          const char *node_name = fdt_get_name(blob, offset, NULL);
> > >>>> +
> > >>>> +          /*
> > >>>> +           * The "chosen" and "firmware" nodes aren't devices
> > >>>> +           * themselves but may contain some:
> > >>>> +           */
> > >>>> +          if (!strcmp(node_name, "chosen") ||
> > >>>> +              !strcmp(node_name, "firmware")) {
> > >>>> +                  pr_debug("parsing subnodes of \"%s\"\n", node_name);
> > >>>>
> > >>>>                    err = dm_scan_fdt_node(parent, blob, offset,
> > >>>>                                           pre_reloc_only);
> > >>>
> > >>> So, the /firmware node seems special.  Have you talked with the
> > >>> devicetree folks to get it listed in the spec?  That would seem rather
> > >>> valuable for something used by many parties.  Thanks!
> > >>>
> > >>
> > >> some days ago we have sent a patch for this too.
> > >> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
> > >>
> > >> It is using different way but it should do the same thing.
> > >
> > > OK, so it sounds like in terms of code clean-ups, we need something like
> > > what you reference and then some further clean-ups on top of that
> > > perhaps for other places to call dm_scan_fdt_ofnode_path() for special
> > > cases.  And in terms of formalized specification bits, I do think
> > > /firmware should perhaps get kicked up to the spec itself so that it's
> > > very clear to all consumers.
> >
> > I was also checking latest devicetree spec and there is no record about
> > /firmware node and how it is supposed to be used.
> 
> Patches welcome. :)
> 
> It's really only a container to define non-discoverable firmware
> interfaces. Typically accessed thru a secure call (for ARM) or a
> mailbox. It is primarily just convention rather than a strict
> requirement. We have to support firmware nodes at the top-level too
> anyways.

Right.  To be clear, I'm suggesting that someone (I was thinking Jens)
pop over to the devicetree-spec list and ask about adding _something_
there as "firmware" isn't even on the list of generic names and may even
warrant something in section 3 under base device node types.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180815/d176b2cc/attachment.sig>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH 01/10] dm: fdt: scan for devices under /firmware too
@ 2018-08-15 15:43               ` Tom Rini
  0 siblings, 0 replies; 40+ messages in thread
From: Tom Rini @ 2018-08-15 15:43 UTC (permalink / raw)
  To: Rob Herring; +Cc: devicetree-spec, U-Boot Mailing List, p.aubert, Michal Simek


[-- Attachment #1.1: Type: text/plain, Size: 3656 bytes --]

On Wed, Aug 15, 2018 at 09:31:30AM -0600, Rob Herring wrote:
> On Wed, Aug 15, 2018 at 8:51 AM Michal Simek <michal.simek@xilinx.com> wrote:
> >
> > Hi Rob,
> >
> > On 15.8.2018 16:34, Tom Rini wrote:
> > > On Wed, Aug 15, 2018 at 04:30:15PM +0200, Michal Simek wrote:
> > >> On 15.8.2018 16:17, Tom Rini wrote:
> > >>> On Mon, Aug 13, 2018 at 05:53:38PM +0200, Jens Wiklander wrote:
> > >>>
> > >>>> Just as /chosen may contain devices /firmware may contain devices, scan
> > >>>> for devices under /firmware too.
> > >>>>
> > >>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> > >>>> ---
> > >>>>  drivers/core/root.c | 15 ++++++++++-----
> > >>>>  1 file changed, 10 insertions(+), 5 deletions(-)
> > >>>>
> > >>>> diff --git a/drivers/core/root.c b/drivers/core/root.c
> > >>>> index 72bcc7d7f2a3..0dca507e1187 100644
> > >>>> --- a/drivers/core/root.c
> > >>>> +++ b/drivers/core/root.c
> > >>>> @@ -265,9 +265,15 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob,
> > >>>>    for (offset = fdt_first_subnode(blob, offset);
> > >>>>         offset > 0;
> > >>>>         offset = fdt_next_subnode(blob, offset)) {
> > >>>> -          /* "chosen" node isn't a device itself but may contain some: */
> > >>>> -          if (!strcmp(fdt_get_name(blob, offset, NULL), "chosen")) {
> > >>>> -                  pr_debug("parsing subnodes of \"chosen\"\n");
> > >>>> +          const char *node_name = fdt_get_name(blob, offset, NULL);
> > >>>> +
> > >>>> +          /*
> > >>>> +           * The "chosen" and "firmware" nodes aren't devices
> > >>>> +           * themselves but may contain some:
> > >>>> +           */
> > >>>> +          if (!strcmp(node_name, "chosen") ||
> > >>>> +              !strcmp(node_name, "firmware")) {
> > >>>> +                  pr_debug("parsing subnodes of \"%s\"\n", node_name);
> > >>>>
> > >>>>                    err = dm_scan_fdt_node(parent, blob, offset,
> > >>>>                                           pre_reloc_only);
> > >>>
> > >>> So, the /firmware node seems special.  Have you talked with the
> > >>> devicetree folks to get it listed in the spec?  That would seem rather
> > >>> valuable for something used by many parties.  Thanks!
> > >>>
> > >>
> > >> some days ago we have sent a patch for this too.
> > >> https://lists.denx.de/pipermail/u-boot/2018-August/338049.html
> > >>
> > >> It is using different way but it should do the same thing.
> > >
> > > OK, so it sounds like in terms of code clean-ups, we need something like
> > > what you reference and then some further clean-ups on top of that
> > > perhaps for other places to call dm_scan_fdt_ofnode_path() for special
> > > cases.  And in terms of formalized specification bits, I do think
> > > /firmware should perhaps get kicked up to the spec itself so that it's
> > > very clear to all consumers.
> >
> > I was also checking latest devicetree spec and there is no record about
> > /firmware node and how it is supposed to be used.
> 
> Patches welcome. :)
> 
> It's really only a container to define non-discoverable firmware
> interfaces. Typically accessed thru a secure call (for ARM) or a
> mailbox. It is primarily just convention rather than a strict
> requirement. We have to support firmware nodes at the top-level too
> anyways.

Right.  To be clear, I'm suggesting that someone (I was thinking Jens)
pop over to the devicetree-spec list and ask about adding _something_
there as "firmware" isn't even on the list of generic names and may even
warrant something in section 3 under base device node types.

-- 
Tom

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-08-13 15:53 ` [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
@ 2018-08-16 12:13   ` Igor Opaniuk
  2018-08-22 13:52     ` Jens Wiklander
  0 siblings, 1 reply; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-16 12:13 UTC (permalink / raw)
  To: u-boot

As I didn't have any available Hikey board, tested this on Poplar:

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>

BTW, we've had it up for discussion already, but just to clarify and summarize:
As ID of eMMC is hardcoded in the OP-TEE OS core (CFG_RPMB_FS_DEV_ID),
we will probably have issues on some platforms, where there is a
difference in the probe order of MMC controllers (for example, on
Poplar eMMC is 0 in U-boot, but in Linux it's 1, as SD is enumerated
as 0).
I guess it's unlikely that people will introduce changes to
U-boot/Linux to make this order conform to each other, so instead, we
should let the Normal World-part to decide what eMMC id to use from
these RPMB frames.

Added Joakim and Jerome so they can follow this thread.

Thanks

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds mmc_rpmb_route_frames() to route RPMB data frames from/to an
> external entity.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  drivers/mmc/rpmb.c | 160 +++++++++++++++++++++++++++++++++++++++++++++
>  include/mmc.h      |   2 +
>  2 files changed, 162 insertions(+)
>
> diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c
> index dfbdb0deb107..908f19208955 100644
> --- a/drivers/mmc/rpmb.c
> +++ b/drivers/mmc/rpmb.c
> @@ -321,3 +321,163 @@ int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
>         }
>         return i;
>  }
> +
> +static int send_write_mult_block(struct mmc *mmc, const struct s_rpmb *frm,
> +                                unsigned short cnt)
> +{
> +       struct mmc_cmd cmd = {
> +               .cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK,
> +               .resp_type = MMC_RSP_R1b,
> +       };
> +       struct mmc_data data = {
> +               .src = (const void *)frm,
> +               .blocks = cnt,
> +               .blocksize = sizeof(*frm),
> +               .flags = MMC_DATA_WRITE,
> +       };
> +
> +       return mmc_send_cmd(mmc, &cmd, &data);
> +}
> +
> +static int send_read_mult_block(struct mmc *mmc, struct s_rpmb *frm,
> +                               unsigned short cnt)
> +{
> +       struct mmc_cmd cmd = {
> +               .cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK,
> +               .resp_type = MMC_RSP_R1,
> +       };
> +       struct mmc_data data = {
> +               .dest = (void *)frm,
> +               .blocks = cnt,
> +               .blocksize = sizeof(*frm),
> +               .flags = MMC_DATA_READ,
> +       };
> +
> +       return mmc_send_cmd(mmc, &cmd, &data);
> +}
> +
> +static int rpmb_route_write_req(struct mmc *mmc, struct s_rpmb *req,
> +                               unsigned short req_cnt, struct s_rpmb *rsp,
> +                               unsigned short rsp_cnt)
> +{
> +       int ret;
> +
> +       /*
> +        * Send the write request.
> +        */
> +       ret = mmc_set_blockcount(mmc, req_cnt, true);
> +       if (ret)
> +               return ret;
> +
> +       ret = send_write_mult_block(mmc, req, req_cnt);
> +       if (ret)
> +               return ret;
> +
> +       /*
> +        * Read the result of the request.
> +        */
> +       ret = mmc_set_blockcount(mmc, 1, false);
> +       if (ret)
> +               return ret;
> +
> +       memset(rsp, 0, sizeof(*rsp));
> +       rsp->request = cpu_to_be16(RPMB_REQ_STATUS);
> +       ret = send_write_mult_block(mmc, rsp, 1);
> +       if (ret)
> +               return ret;
> +
> +       ret = mmc_set_blockcount(mmc, 1, false);
> +       if (ret)
> +               return ret;
> +
> +       return send_read_mult_block(mmc, rsp, 1);
> +}
> +
> +static int rpmb_route_read_req(struct mmc *mmc, struct s_rpmb *req,
> +                              unsigned short req_cnt, struct s_rpmb *rsp,
> +                              unsigned short rsp_cnt)
> +{
> +       int ret;
> +
> +       /*
> +        * Send the read request.
> +        */
> +       ret = mmc_set_blockcount(mmc, 1, false);
> +       if (ret)
> +               return ret;
> +
> +       ret = send_write_mult_block(mmc, req, 1);
> +       if (ret)
> +               return ret;
> +
> +       /*
> +        * Read the result of the request.
> +        */
> +
> +       ret = mmc_set_blockcount(mmc, rsp_cnt, false);
> +       if (ret)
> +               return ret;
> +
> +       return send_read_mult_block(mmc, rsp, rsp_cnt);
> +}
> +
> +static int rpmb_route_frames(struct mmc *mmc, struct s_rpmb *req,
> +                            unsigned short req_cnt, struct s_rpmb *rsp,
> +                            unsigned short rsp_cnt)
> +{
> +       unsigned short n;
> +
> +       /*
> +        * If multiple request frames are provided, make sure that all are
> +        * of the same type.
> +        */
> +       for (n = 1; n < req_cnt; n++)
> +               if (req[n].request != req->request)
> +                       return -EINVAL;
> +
> +       switch (be16_to_cpu(req->request)) {
> +       case RPMB_REQ_KEY:
> +               if (req_cnt != 1 || rsp_cnt != 1)
> +                       return -EINVAL;
> +               return rpmb_route_write_req(mmc, req, req_cnt, rsp, rsp_cnt);
> +
> +       case RPMB_REQ_WRITE_DATA:
> +               if (!req_cnt || rsp_cnt != 1)
> +                       return -EINVAL;
> +               return rpmb_route_write_req(mmc, req, req_cnt, rsp, rsp_cnt);
> +
> +       case RPMB_REQ_WCOUNTER:
> +               if (req_cnt != 1 || rsp_cnt != 1)
> +                       return -EINVAL;
> +               return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
> +
> +       case RPMB_REQ_READ_DATA:
> +               if (req_cnt != 1 || !req_cnt)
> +                       return -EINVAL;
> +               return rpmb_route_read_req(mmc, req, req_cnt, rsp, rsp_cnt);
> +
> +       default:
> +               debug("Unsupported message type: %d\n",
> +                     be16_to_cpu(req->request));
> +               return -EINVAL;
> +       }
> +}
> +
> +int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
> +                         void *rsp, unsigned long rsplen)
> +{
> +       /*
> +        * Whoever crafted the data supplied to this function knows how to
> +        * format the PRMB frames and which response is expected. If
> +        * there's some unexpected mismatch it's more helpful to report an
> +        * error immediately than trying to guess what was the intention
> +        * and possibly just delay an eventual error which will be harder
> +        * to track down.
> +        */
> +
> +       if (reqlen % sizeof(struct s_rpmb) || rsplen % sizeof(struct s_rpmb))
> +               return -EINVAL;
> +
> +       return rpmb_route_frames(mmc, req, reqlen / sizeof(struct s_rpmb),
> +                                rsp, rsplen / sizeof(struct s_rpmb));
> +}
> diff --git a/include/mmc.h b/include/mmc.h
> index df4255b828a7..d6e02af4edea 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -748,6 +748,8 @@ int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
>                   unsigned short cnt, unsigned char *key);
>  int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
>                    unsigned short cnt, unsigned char *key);
> +int mmc_rpmb_route_frames(struct mmc *mmc, void *req, unsigned long reqlen,
> +                         void *rsp, unsigned long rsplen);
>  #ifdef CONFIG_CMD_BKOPS_ENABLE
>  int mmc_set_bkops_enable(struct mmc *mmc);
>  #endif
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-13 15:53 ` [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
@ 2018-08-16 12:14   ` Igor Opaniuk
  2018-08-17 12:48   ` Simon Glass
  2018-08-23 10:45   ` Simon Glass
  2 siblings, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-16 12:14 UTC (permalink / raw)
  To: u-boot

Tested this on Poplar:

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds a uclass to interface with a TEE (Trusted Execution Environment).
>
> A TEE driver is a driver that interfaces with a trusted OS running in
> some secure environment, for example, TrustZone on ARM cpus, or a
> separate secure co-processor etc.
>
> The TEE subsystem can serve a TEE driver for a Global Platform compliant
> TEE, but it's not limited to only Global Platform TEEs.
>
> The over all design is based on the TEE subsystem in the Linux kernel,
> tailored for U-boot.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  MAINTAINERS              |   6 ++
>  drivers/Kconfig          |   2 +
>  drivers/Makefile         |   1 +
>  drivers/tee/Kconfig      |   8 ++
>  drivers/tee/Makefile     |   3 +
>  drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h   |   1 +
>  include/tee.h            | 134 +++++++++++++++++++++++++++++
>  8 files changed, 335 insertions(+)
>  create mode 100644 drivers/tee/Kconfig
>  create mode 100644 drivers/tee/Makefile
>  create mode 100644 drivers/tee/tee-uclass.c
>  create mode 100644 include/tee.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 58b61ac05882..7458c606ee92 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -571,6 +571,12 @@ TQ GROUP
>  S:     Orphaned (Since 2016-02)
>  T:     git git://git.denx.de/u-boot-tq-group.git
>
> +TEE
> +M:     Jens Wiklander <jens.wiklander@linaro.org>
> +S:     Maintained
> +F:     drivers/tee/
> +F:     include/tee.h
> +
>  UBI
>  M:     Kyungmin Park <kmpark@infradead.org>
>  M:     Heiko Schocher <hs@denx.de>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c72abf893297..f3249ab1d143 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
>
>  source "drivers/sysreset/Kconfig"
>
> +source "drivers/tee/Kconfig"
> +
>  source "drivers/thermal/Kconfig"
>
>  source "drivers/timer/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index d53208540ea6..0fcae36f50f7 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -103,6 +103,7 @@ obj-y += smem/
>  obj-y += soc/
>  obj-$(CONFIG_REMOTEPROC) += remoteproc/
>  obj-y += thermal/
> +obj-$(CONFIG_TEE) += tee/
>
>  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
>  endif
> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
> new file mode 100644
> index 000000000000..817ab331b0f8
> --- /dev/null
> +++ b/drivers/tee/Kconfig
> @@ -0,0 +1,8 @@
> +# Generic Trusted Execution Environment Configuration
> +config TEE
> +       bool "Trusted Execution Environment support"
> +       depends on ARM && (ARM64 || CPU_V7A)
> +       select ARM_SMCCC
> +       help
> +         This implements a generic interface towards a Trusted Execution
> +         Environment (TEE).
> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> new file mode 100644
> index 000000000000..b6d8e16e6211
> --- /dev/null
> +++ b/drivers/tee/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += tee-uclass.o
> diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
> new file mode 100644
> index 000000000000..f0243a0f2e4e
> --- /dev/null
> +++ b/drivers/tee/tee-uclass.c
> @@ -0,0 +1,180 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <tee.h>
> +
> +struct tee_uclass_priv {
> +       struct list_head list_shm;
> +};
> +
> +static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
> +{
> +       return device_get_ops(dev);
> +}
> +
> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
> +{
> +       tee_get_ops(dev)->get_version(dev, vers);
> +}
> +
> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> +                    ulong num_param, struct tee_param *param)
> +{
> +       return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
> +}
> +
> +int tee_close_session(struct udevice *dev, u32 session)
> +{
> +       return tee_get_ops(dev)->close_session(dev, session);
> +}
> +
> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                   ulong num_param, struct tee_param *param)
> +{
> +       return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
> +}
> +
> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> +                             ulong size, u32 flags)
> +{
> +       struct tee_shm *shm;
> +       void *p = addr;
> +
> +       if (flags & TEE_SHM_ALLOC) {
> +               if (align)
> +                       p = memalign(align, size);
> +               else
> +                       p = malloc(size);
> +       }
> +       if (!p)
> +               return NULL;
> +
> +       shm = calloc(1, sizeof(*shm));
> +       if (!shm)
> +               goto err;
> +
> +       shm->dev = dev;
> +       shm->addr = p;
> +       shm->size = size;
> +       shm->flags = flags;
> +
> +       if ((flags & TEE_SHM_SEC_REGISTER) &&
> +           tee_get_ops(dev)->shm_register(dev, shm))
> +               goto err;
> +
> +       if (flags & TEE_SHM_REGISTER) {
> +               struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +
> +               list_add(&shm->link, &priv->list_shm);
> +       }
> +       return shm;
> +err:
> +       free(shm);
> +       if (flags & TEE_SHM_ALLOC)
> +               free(p);
> +       return NULL;
> +}
> +
> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
> +                             u32 flags)
> +{
> +       u32 f = flags;
> +
> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
> +       return __tee_shm_add(dev, 0, NULL, size, f);
> +}
> +
> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> +                                ulong size, u32 flags)
> +{
> +       u32 f = flags & ~TEE_SHM_ALLOC;
> +
> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
> +       return __tee_shm_add(dev, 0, addr, size, f);
> +}
> +
> +void tee_shm_free(struct tee_shm *shm)
> +{
> +       if (!shm)
> +               return;
> +
> +       if (shm->flags & TEE_SHM_SEC_REGISTER)
> +               tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
> +
> +       if (shm->flags & TEE_SHM_REGISTER)
> +               list_del(&shm->link);
> +
> +       if (shm->flags & TEE_SHM_ALLOC)
> +               free(shm->addr);
> +
> +       free(shm);
> +}
> +
> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +       struct tee_shm *s;
> +
> +       list_for_each_entry(s, &priv->list_shm, link)
> +               if (s == shm)
> +                       return true;
> +
> +       return false;
> +}
> +
> +struct udevice *tee_find_device(struct udevice *start,
> +                               int (*match)(struct tee_version_data *vers,
> +                                            const void *data),
> +                               const void *data,
> +                               struct tee_version_data *vers)
> +{
> +       struct udevice *dev = start;
> +       struct tee_version_data lv;
> +       struct tee_version_data *v = vers ? vers : &lv;
> +
> +       if (!dev)
> +               uclass_first_device(UCLASS_TEE, &dev);
> +
> +       for (; dev; uclass_next_device(&dev)) {
> +               tee_get_ops(dev)->get_version(dev, v);
> +               if (!match || match(v, data))
> +                       return dev;
> +       }
> +
> +       return NULL;
> +}
> +
> +static int tee_pre_probe(struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +
> +       INIT_LIST_HEAD(&priv->list_shm);
> +       return 0;
> +}
> +
> +static int tee_pre_remove(struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +       struct tee_shm *shm;
> +
> +       while (!list_empty(&priv->list_shm)) {
> +               shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
> +               debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
> +                     __func__, (void *)shm, shm->size, shm->flags);
> +               tee_shm_free(shm);
> +       }
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(tee) = {
> +       .id = UCLASS_TEE,
> +       .name = "tee",
> +       .per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
> +       .pre_probe = tee_pre_probe,
> +       .pre_remove = tee_pre_remove,
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a39643ec5eef..955e0a915b87 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -81,6 +81,7 @@ enum uclass_id {
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
>         UCLASS_SYSRESET,        /* System reset device */
> +       UCLASS_TEE,             /* Trusted Execution Environment device */
>         UCLASS_THERMAL,         /* Thermal sensor */
>         UCLASS_TIMER,           /* Timer device */
>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
> diff --git a/include/tee.h b/include/tee.h
> new file mode 100644
> index 000000000000..c2ac13e34128
> --- /dev/null
> +++ b/include/tee.h
> @@ -0,0 +1,134 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#ifndef __TEE_H
> +#define __TEE_H
> +
> +#include <common.h>
> +#include <dm.h>
> +
> +#define TEE_UUID_LEN           16
> +
> +#define TEE_GEN_CAP_GP          BIT(0) /* GlobalPlatform compliant TEE */
> +#define TEE_GEN_CAP_REG_MEM     BIT(1) /* Supports registering shared memory */
> +
> +#define TEE_SHM_REGISTER       BIT(0)
> +#define TEE_SHM_SEC_REGISTER   BIT(1)
> +#define TEE_SHM_ALLOC          BIT(2)
> +
> +#define TEE_PARAM_ATTR_TYPE_NONE               0       /* parameter not used */
> +#define TEE_PARAM_ATTR_TYPE_VALUE_INPUT                1
> +#define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT       2
> +#define TEE_PARAM_ATTR_TYPE_VALUE_INOUT                3       /* input and output */
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT       5
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT      6
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT       7       /* input and output */
> +#define TEE_PARAM_ATTR_TYPE_MASK               0xff
> +#define TEE_PARAM_ATTR_META                    0x100
> +#define TEE_PARAM_ATTR_MASK                    (TEE_PARAM_ATTR_TYPE_MASK | \
> +                                                TEE_PARAM_ATTR_META)
> +
> +/*
> + * Some Global Platform error codes which has a meaning if the
> + * TEE_GEN_CAP_GP bit is returned by the driver.
> + */
> +#define TEE_SUCCESS                    0x00000000
> +#define TEE_ERROR_GENERIC              0xffff0000
> +#define TEE_ERROR_BAD_PARAMETERS       0xffff0006
> +#define TEE_ERROR_ITEM_NOT_FOUND       0xffff0008
> +#define TEE_ERROR_NOT_IMPLEMENTED      0xffff0009
> +#define TEE_ERROR_NOT_SUPPORTED                0xffff000a
> +#define TEE_ERROR_COMMUNICATION                0xffff000e
> +#define TEE_ERROR_OUT_OF_MEMORY                0xffff000c
> +#define TEE_ERROR_TARGET_DEAD          0xffff3024
> +
> +#define TEE_ORIGIN_COMMS               0x00000002
> +
> +struct tee_driver_ops;
> +
> +struct tee_shm {
> +       struct udevice *dev;
> +       struct list_head link;
> +       void *addr;
> +       ulong size;
> +       u32 flags;
> +};
> +
> +struct tee_param_memref {
> +       ulong shm_offs;
> +       ulong size;
> +       struct tee_shm *shm;
> +};
> +
> +struct tee_param_value {
> +       u64 a;
> +       u64 b;
> +       u64 c;
> +};
> +
> +struct tee_param {
> +       u64 attr;
> +       union {
> +               struct tee_param_memref memref;
> +               struct tee_param_value value;
> +       } u;
> +};
> +
> +struct tee_open_session_arg {
> +       u8 uuid[TEE_UUID_LEN];
> +       u8 clnt_uuid[TEE_UUID_LEN];
> +       u32 clnt_login;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +struct tee_invoke_arg {
> +       u32 func;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +struct tee_version_data {
> +       u32 gen_caps;
> +};
> +
> +struct tee_driver_ops {
> +       void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
> +       int (*open_session)(struct udevice *dev,
> +                           struct tee_open_session_arg *arg, ulong num_param,
> +                           struct tee_param *param);
> +       int (*close_session)(struct udevice *dev, u32 session);
> +       int (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
> +                          ulong num_param, struct tee_param *param);
> +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
> +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
> +};
> +
> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> +                             ulong size, u32 flags);
> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);
> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> +                                ulong length, u32 flags);
> +void tee_shm_free(struct tee_shm *shm);
> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
> +
> +struct udevice *tee_find_device(struct udevice *start,
> +                               int (*match)(struct tee_version_data *vers,
> +                                            const void *data),
> +                               const void *data,
> +                               struct tee_version_data *vers);
> +
> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> +                    ulong num_param, struct tee_param *param);
> +
> +int tee_close_session(struct udevice *dev, u32 session);
> +
> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                   ulong num_param, struct tee_param *param);
> +
> +#endif /*__TEE_H*/
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB
  2018-08-14 11:20   ` Igor Opaniuk
@ 2018-08-16 12:17     ` Igor Opaniuk
  0 siblings, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-16 12:17 UTC (permalink / raw)
  To: u-boot

Hi Jens,

Minor issue:
There should be some error message when we try to write Ñ„ rollback
index, which value is less than existing. For example:
poplar# avb write_rb 1 4
poplar# avb read_rb 1
Rollback index: 4
poplar# avb write_rb 1 3   // Should print error message here
poplar# avb read_rb 1
Rollback index: 4

Otherwise:
Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 14 August 2018 at 14:20, Igor Opaniuk <igor.opaniuk@linaro.org> wrote:
> Hi Jens,
>
> Could you please also add info about CONFIG_OPTEE_TA_AVB to the
> existing doc/README.avb2 and more description of
> how/where rollback indexes/device lock state are stored (this what you
> explained in the cover letter for this patchset).
>
> Thanks
>
> On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> With CONFIG_OPTEE_TA_AVB use the trusted application AVB provided by
>> OP-TEE to manage rollback indexes and device lock status.
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  common/avb_verify.c  | 132 ++++++++++++++++++++++++++++++++++++++++++-
>>  include/avb_verify.h |   4 ++
>>  2 files changed, 135 insertions(+), 1 deletion(-)
>>
>> diff --git a/common/avb_verify.c b/common/avb_verify.c
>> index 20e35ade3029..a50c05bf7847 100644
>> --- a/common/avb_verify.c
>> +++ b/common/avb_verify.c
>> @@ -10,6 +10,8 @@
>>  #include <image.h>
>>  #include <malloc.h>
>>  #include <part.h>
>> +#include <tee.h>
>> +#include <tee/optee_ta_avb.h>
>>
>>  const unsigned char avb_root_pub[1032] = {
>>         0x0, 0x0, 0x10, 0x0, 0x55, 0xd9, 0x4, 0xad, 0xd8, 0x4,
>> @@ -594,6 +596,79 @@ static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
>>         return AVB_IO_RESULT_OK;
>>  }
>>
>> +#ifdef CONFIG_OPTEE_TA_AVB
>> +static void uuid_to_octets(u8 d[TEE_UUID_LEN],
>> +                          const struct tee_optee_ta_uuid *s)
>> +{
>> +       d[0] = s->time_low >> 24;
>> +       d[1] = s->time_low >> 16;
>> +       d[2] = s->time_low >> 8;
>> +       d[3] = s->time_low;
>> +       d[4] = s->time_mid >> 8;
>> +       d[5] = s->time_mid;
>> +       d[6] = s->time_hi_and_version >> 8;
>> +       d[7] = s->time_hi_and_version;
>> +       memcpy(d + 8, s->clock_seq_and_node, sizeof(s->clock_seq_and_node));
>> +}
>> +
>> +static int get_open_session(struct AvbOpsData *ops_data)
>> +{
>> +       struct udevice *tee = NULL;
>> +
>> +       while (!ops_data->tee) {
>> +               const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
>> +               struct tee_open_session_arg arg;
>> +               int rc;
>> +
>> +               tee = tee_find_device(tee, NULL, NULL, NULL);
>> +               if (!tee)
>> +                       return -ENODEV;
>> +
>> +               memset(&arg, 0, sizeof(arg));
>> +               uuid_to_octets(arg.uuid, &uuid);
>> +               rc = tee_open_session(tee, &arg, 0, NULL);
>> +               if (!rc) {
>> +                       ops_data->tee = tee;
>> +                       ops_data->session = arg.session;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static AvbIOResult invoke_func(struct AvbOpsData *ops_data, u32 func,
>> +                              ulong num_param, struct tee_param *param)
>> +{
>> +       struct tee_invoke_arg arg;
>> +
>> +       if (get_open_session(ops_data))
>> +               return AVB_IO_RESULT_ERROR_IO;
>> +
>> +       memset(&arg, 0, sizeof(arg));
>> +       arg.func = func;
>> +       arg.session = ops_data->session;
>> +
>> +       if (tee_invoke_func(ops_data->tee, &arg, num_param, param))
>> +               return AVB_IO_RESULT_ERROR_IO;
>> +       switch (arg.ret) {
>> +       case TEE_SUCCESS:
>> +               return AVB_IO_RESULT_OK;
>> +       case TEE_ERROR_OUT_OF_MEMORY:
>> +               return AVB_IO_RESULT_ERROR_OOM;
>> +       case TEE_ERROR_TARGET_DEAD:
>> +               /*
>> +                * The TA has paniced, close the session to reload the TA
>> +                * for the next request.
>> +                */
>> +               tee_close_session(ops_data->tee, ops_data->session);
>> +               ops_data->tee = NULL;
>> +               return AVB_IO_RESULT_ERROR_IO;
>> +       default:
>> +               return AVB_IO_RESULT_ERROR_IO;
>> +       }
>> +}
>> +#endif
>> +
>>  /**
>>   * read_rollback_index() - gets the rollback index corresponding to the
>>   * location of given by @out_rollback_index.
>> @@ -609,6 +684,7 @@ static AvbIOResult read_rollback_index(AvbOps *ops,
>>                                        size_t rollback_index_slot,
>>                                        u64 *out_rollback_index)
>>  {
>> +#ifndef CONFIG_OPTEE_TA_AVB
>>         /* For now we always return 0 as the stored rollback index. */
>>         printf("%s not supported yet\n", __func__);
>>
>> @@ -616,6 +692,27 @@ static AvbIOResult read_rollback_index(AvbOps *ops,
>>                 *out_rollback_index = 0;
>>
>>         return AVB_IO_RESULT_OK;
>> +#else
>> +       AvbIOResult rc;
>> +       struct tee_param param[2];
>> +
>> +       if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
>> +               return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
>> +
>> +       memset(param, 0, sizeof(param));
>> +       param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
>> +       param[0].u.value.a = rollback_index_slot;
>> +       param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
>> +
>> +       rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_ROLLBACK_INDEX,
>> +                        ARRAY_SIZE(param), param);
>> +       if (rc)
>> +               return rc;
>> +
>> +       *out_rollback_index = (u64)param[1].u.value.a << 32 |
>> +                             (u32)param[1].u.value.b;
>> +       return AVB_IO_RESULT_OK;
>> +#endif
>>  }
>>
>>  /**
>> @@ -633,10 +730,27 @@ static AvbIOResult write_rollback_index(AvbOps *ops,
>>                                         size_t rollback_index_slot,
>>                                         u64 rollback_index)
>>  {
>> +#ifndef CONFIG_OPTEE_TA_AVB
>>         /* For now this is a no-op. */
>>         printf("%s not supported yet\n", __func__);
>>
>>         return AVB_IO_RESULT_OK;
>> +#else
>> +       struct tee_param param[2];
>> +
>> +       if (rollback_index_slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS)
>> +               return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
>> +
>> +       memset(param, 0, sizeof(param));
>> +       param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
>> +       param[0].u.value.a = rollback_index_slot;
>> +       param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
>> +       param[1].u.value.a = (u32)(rollback_index >> 32);
>> +       param[1].u.value.b = (u32)rollback_index;
>> +
>> +       return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_ROLLBACK_INDEX,
>> +                          ARRAY_SIZE(param), param);
>> +#endif
>>  }
>>
>>  /**
>> @@ -652,6 +766,7 @@ static AvbIOResult write_rollback_index(AvbOps *ops,
>>   */
>>  static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
>>  {
>> +#ifndef CONFIG_OPTEE_TA_AVB
>>         /* For now we always return that the device is unlocked. */
>>
>>         printf("%s not supported yet\n", __func__);
>> @@ -659,6 +774,16 @@ static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked)
>>         *out_is_unlocked = true;
>>
>>         return AVB_IO_RESULT_OK;
>> +#else
>> +       AvbIOResult rc;
>> +       struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
>> +
>> +       rc = invoke_func(ops->user_data, TA_AVB_CMD_READ_LOCK_STATE, 1, &param);
>> +       if (rc)
>> +               return rc;
>> +       *out_is_unlocked = !param.u.value.a;
>> +       return AVB_IO_RESULT_OK;
>> +#endif
>>  }
>>
>>  /**
>> @@ -737,6 +862,11 @@ void avb_ops_free(AvbOps *ops)
>>
>>         ops_data = ops->user_data;
>>
>> -       if (ops_data)
>> +       if (ops_data) {
>> +#ifdef CONFIG_OPTEE_TA_AVB
>> +               if (ops_data->tee)
>> +                       tee_close_session(ops_data->tee, ops_data->session);
>> +#endif
>>                 avb_free(ops_data);
>> +       }
>>  }
>> diff --git a/include/avb_verify.h b/include/avb_verify.h
>> index eaa60f5393ef..a532a2331aea 100644
>> --- a/include/avb_verify.h
>> +++ b/include/avb_verify.h
>> @@ -27,6 +27,10 @@ struct AvbOpsData {
>>         struct AvbOps ops;
>>         int mmc_dev;
>>         enum avb_boot_state boot_state;
>> +#ifdef CONFIG_OPTEE_TA_AVB
>> +       struct udevice *tee;
>> +       u32 session;
>> +#endif
>>  };
>>
>>  struct mmc_part {
>> --
>> 2.17.1
>>
>
>
>
> --
> Regards,
> Igor Opaniuk



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 06/10] tee: add OP-TEE driver
  2018-08-13 15:53 ` [U-Boot] [PATCH 06/10] tee: add OP-TEE driver Jens Wiklander
@ 2018-08-16 12:17   ` Igor Opaniuk
  0 siblings, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-16 12:17 UTC (permalink / raw)
  To: u-boot

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds a OP-TEE driver.
>
> * Targets ARM and ARM64
> * Supports using any u-boot memory as shared memory
> * Probes OP-TEE version using SMCs
> * Uses OPTEE message protocol version 2 to communicate with secure world
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  drivers/tee/Kconfig                      |  10 +
>  drivers/tee/Makefile                     |   1 +
>  drivers/tee/optee/Kconfig                |   7 +
>  drivers/tee/optee/Makefile               |   4 +
>  drivers/tee/optee/core.c                 | 614 +++++++++++++++++++++++
>  drivers/tee/optee/optee_msg.h            | 423 ++++++++++++++++
>  drivers/tee/optee/optee_msg_supplicant.h | 234 +++++++++
>  drivers/tee/optee/optee_private.h        |  12 +
>  drivers/tee/optee/optee_smc.h            | 444 ++++++++++++++++
>  drivers/tee/optee/supplicant.c           |  89 ++++
>  10 files changed, 1838 insertions(+)
>  create mode 100644 drivers/tee/optee/Kconfig
>  create mode 100644 drivers/tee/optee/Makefile
>  create mode 100644 drivers/tee/optee/core.c
>  create mode 100644 drivers/tee/optee/optee_msg.h
>  create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
>  create mode 100644 drivers/tee/optee/optee_private.h
>  create mode 100644 drivers/tee/optee/optee_smc.h
>  create mode 100644 drivers/tee/optee/supplicant.c
>
> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
> index 817ab331b0f8..3e7fe6ddcc5d 100644
> --- a/drivers/tee/Kconfig
> +++ b/drivers/tee/Kconfig
> @@ -6,3 +6,13 @@ config TEE
>         help
>           This implements a generic interface towards a Trusted Execution
>           Environment (TEE).
> +
> +if TEE
> +
> +menu "TEE drivers"
> +
> +source "drivers/tee/optee/Kconfig"
> +
> +endmenu
> +
> +endif
> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> index b6d8e16e6211..19633b60f235 100644
> --- a/drivers/tee/Makefile
> +++ b/drivers/tee/Makefile
> @@ -1,3 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0+
>
>  obj-y += tee-uclass.o
> +obj-$(CONFIG_OPTEE) += optee/
> diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
> new file mode 100644
> index 000000000000..8f7ebe161111
> --- /dev/null
> +++ b/drivers/tee/optee/Kconfig
> @@ -0,0 +1,7 @@
> +# OP-TEE Trusted Execution Environment Configuration
> +config OPTEE
> +       bool "OP-TEE"
> +       depends on ARM_SMCCC
> +       help
> +         This implements the OP-TEE Trusted Execution Environment (TEE)
> +         driver.
> diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
> new file mode 100644
> index 000000000000..6148feb474a5
> --- /dev/null
> +++ b/drivers/tee/optee/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += core.o
> +obj-y += supplicant.o
> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> new file mode 100644
> index 000000000000..a810f3b965de
> --- /dev/null
> +++ b/drivers/tee/optee/core.c
> @@ -0,0 +1,614 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <linux/arm-smccc.h>
> +#include <linux/io.h>
> +#include <log.h>
> +#include <tee.h>
> +
> +#include "optee_smc.h"
> +#include "optee_msg.h"
> +#include "optee_private.h"
> +
> +#define PAGELIST_ENTRIES_PER_PAGE \
> +       ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
> +
> +typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
> +                              unsigned long, unsigned long, unsigned long,
> +                              unsigned long, unsigned long,
> +                              struct arm_smccc_res *);
> +
> +struct optee_pdata {
> +       optee_invoke_fn *invoke_fn;
> +};
> +
> +struct rpc_param {
> +       u32     a0;
> +       u32     a1;
> +       u32     a2;
> +       u32     a3;
> +       u32     a4;
> +       u32     a5;
> +       u32     a6;
> +       u32     a7;
> +};
> +
> +static void *reg_pair_to_ptr(u32 reg0, u32 reg1)
> +{
> +       return (void *)(ulong)(((u64)reg0 << 32) | reg1);
> +}
> +
> +static void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
> +{
> +       *reg0 = val >> 32;
> +       *reg1 = val;
> +}
> +
> +void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr)
> +{
> +       const unsigned int page_size = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
> +       const phys_addr_t page_mask = page_size - 1;
> +       u8 *buf_base;
> +       unsigned int page_offset;
> +       unsigned int num_pages;
> +       unsigned int list_size;
> +       unsigned int n;
> +       void *page_list;
> +       struct {
> +               u64 pages_list[PAGELIST_ENTRIES_PER_PAGE];
> +               u64 next_page_data;
> +       } *pages_data;
> +
> +       page_offset = (ulong)buf & page_mask;
> +       num_pages = roundup(page_offset + len, page_size) / page_size;
> +       list_size = DIV_ROUND_UP(num_pages, PAGELIST_ENTRIES_PER_PAGE) *
> +                   page_size;
> +       page_list = memalign(page_size, list_size);
> +       if (!page_list)
> +               return NULL;
> +
> +       pages_data = page_list;
> +       buf_base = (u8 *)(rounddown((ulong)buf, page_size));
> +       n = 0;
> +       while (num_pages) {
> +               pages_data->pages_list[n] = virt_to_phys(buf_base);
> +               n++;
> +               buf_base += page_size;
> +               num_pages--;
> +
> +               if (n == PAGELIST_ENTRIES_PER_PAGE) {
> +                       pages_data->next_page_data =
> +                               virt_to_phys(pages_data + 1);
> +                       pages_data++;
> +                       n = 0;
> +               }
> +       }
> +
> +       *phys_buf_ptr = virt_to_phys(page_list) | page_offset;
> +       return page_list;
> +}
> +
> +static void optee_get_version(struct udevice *dev,
> +                             struct tee_version_data *vers)
> +{
> +       struct tee_version_data v = {
> +               .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
> +       };
> +
> +       *vers = v;
> +}
> +
> +static struct tee_shm *get_msg_arg(struct udevice *dev, ulong num_params,
> +                                  struct optee_msg_arg **msg_arg)
> +{
> +       struct tee_shm *shm;
> +       struct optee_msg_arg *ma;
> +
> +       shm = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
> +                           OPTEE_MSG_GET_ARG_SIZE(num_params), TEE_SHM_ALLOC);
> +       if (!shm)
> +               return NULL;
> +
> +       ma = shm->addr;
> +       memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
> +       ma->num_params = num_params;
> +       *msg_arg = ma;
> +
> +       return shm;
> +}
> +
> +int to_msg_param(struct optee_msg_param *msg_params, ulong num_params,
> +                const struct tee_param *params)
> +{
> +       ulong n;
> +
> +       for (n = 0; n < num_params; n++) {
> +               const struct tee_param *p = params + n;
> +               struct optee_msg_param *mp = msg_params + n;
> +
> +               switch (p->attr) {
> +               case TEE_PARAM_ATTR_TYPE_NONE:
> +                       mp->attr = OPTEE_MSG_ATTR_TYPE_NONE;
> +                       memset(&mp->u, 0, sizeof(mp->u));
> +                       break;
> +               case TEE_PARAM_ATTR_TYPE_VALUE_INPUT:
> +               case TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT:
> +               case TEE_PARAM_ATTR_TYPE_VALUE_INOUT:
> +                       mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
> +                                  TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
> +                       mp->u.value.a = p->u.value.a;
> +                       mp->u.value.b = p->u.value.b;
> +                       mp->u.value.c = p->u.value.c;
> +                       break;
> +               case TEE_PARAM_ATTR_TYPE_MEMREF_INPUT:
> +               case TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
> +               case TEE_PARAM_ATTR_TYPE_MEMREF_INOUT:
> +                       mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
> +                                  TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
> +                       mp->u.rmem.shm_ref = (ulong)p->u.memref.shm;
> +                       mp->u.rmem.size = p->u.memref.size;
> +                       mp->u.rmem.offs = p->u.memref.shm_offs;
> +                       break;
> +               default:
> +                       return -EINVAL;
> +               }
> +       }
> +       return 0;
> +}
> +
> +static int from_msg_param(struct tee_param *params, ulong num_params,
> +                         const struct optee_msg_param *msg_params)
> +{
> +       ulong n;
> +       struct tee_shm *shm;
> +
> +       for (n = 0; n < num_params; n++) {
> +               struct tee_param *p = params + n;
> +               const struct optee_msg_param *mp = msg_params + n;
> +               u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
> +
> +               switch (attr) {
> +               case OPTEE_MSG_ATTR_TYPE_NONE:
> +                       p->attr = TEE_PARAM_ATTR_TYPE_NONE;
> +                       memset(&p->u, 0, sizeof(p->u));
> +                       break;
> +               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
> +               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
> +               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
> +                       p->attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT + attr -
> +                                 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
> +                       p->u.value.a = mp->u.value.a;
> +                       p->u.value.b = mp->u.value.b;
> +                       p->u.value.c = mp->u.value.c;
> +                       break;
> +               case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
> +               case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
> +               case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
> +                       p->attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT + attr -
> +                                 OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
> +                       p->u.memref.size = mp->u.rmem.size;
> +                       shm = (struct tee_shm *)(ulong)mp->u.rmem.shm_ref;
> +
> +                       if (!shm) {
> +                               p->u.memref.shm_offs = 0;
> +                               p->u.memref.shm = NULL;
> +                               break;
> +                       }
> +                       p->u.memref.shm_offs = mp->u.rmem.offs;
> +                       p->u.memref.shm = shm;
> +                       break;
> +               default:
> +                       return -EINVAL;
> +               }
> +       }
> +       return 0;
> +}
> +
> +static void handle_rpc(struct udevice *dev, struct rpc_param *param,
> +                      void *page_list)
> +{
> +       struct tee_shm *shm;
> +
> +       switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
> +       case OPTEE_SMC_RPC_FUNC_ALLOC:
> +               shm = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
> +                                   param->a1,
> +                                   TEE_SHM_ALLOC | TEE_SHM_REGISTER);
> +               if (shm) {
> +                       reg_pair_from_64(&param->a1, &param->a2,
> +                                        virt_to_phys(shm->addr));
> +                       /* "cookie" */
> +                       reg_pair_from_64(&param->a4, &param->a5, (ulong)shm);
> +               } else {
> +                       param->a1 = 0;
> +                       param->a2 = 0;
> +                       param->a4 = 0;
> +                       param->a5 = 0;
> +               }
> +               break;
> +       case OPTEE_SMC_RPC_FUNC_FREE:
> +               shm = reg_pair_to_ptr(param->a1, param->a2);
> +               tee_shm_free(shm);
> +               break;
> +       case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
> +               break;
> +       case OPTEE_SMC_RPC_FUNC_CMD:
> +               shm = reg_pair_to_ptr(param->a1, param->a2);
> +               optee_suppl_cmd(dev, shm, page_list);
> +               break;
> +       default:
> +               break;
> +       }
> +
> +       param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
> +}
> +
> +static u32 call_err_to_res(u32 call_err)
> +{
> +       switch (call_err) {
> +       case OPTEE_SMC_RETURN_OK:
> +               return TEE_SUCCESS;
> +       default:
> +               return TEE_ERROR_BAD_PARAMETERS;
> +       }
> +}
> +
> +static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg)
> +{
> +       struct optee_pdata *pdata = dev_get_platdata(dev);
> +       struct rpc_param param = { .a0 = OPTEE_SMC_CALL_WITH_ARG };
> +       void *page_list = NULL;
> +
> +       reg_pair_from_64(&param.a1, &param.a2, virt_to_phys(arg));
> +       while (true) {
> +               struct arm_smccc_res res;
> +
> +               pdata->invoke_fn(param.a0, param.a1, param.a2, param.a3,
> +                                param.a4, param.a5, param.a6, param.a7, &res);
> +
> +               free(page_list);
> +               page_list = NULL;
> +
> +               if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
> +                       param.a0 = res.a0;
> +                       param.a1 = res.a1;
> +                       param.a2 = res.a2;
> +                       param.a3 = res.a3;
> +                       handle_rpc(dev, &param, &page_list);
> +               } else {
> +                       return call_err_to_res(res.a0);
> +               }
> +       }
> +}
> +
> +int optee_close_session(struct udevice *dev, u32 session)
> +{
> +       struct tee_shm *shm;
> +       struct optee_msg_arg *msg_arg;
> +
> +       shm = get_msg_arg(dev, 0, &msg_arg);
> +       if (!shm)
> +               return -ENOMEM;
> +
> +       msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
> +       msg_arg->session = session;
> +       do_call_with_arg(dev, msg_arg);
> +
> +       tee_shm_free(shm);
> +       return 0;
> +}
> +
> +static int optee_open_session(struct udevice *dev,
> +                             struct tee_open_session_arg *arg,
> +                             ulong num_params, struct tee_param *params)
> +{
> +       int rc;
> +       struct tee_shm *shm;
> +       struct optee_msg_arg *msg_arg;
> +
> +       shm = get_msg_arg(dev, num_params + 2, &msg_arg);
> +       if (!shm)
> +               return -ENOMEM;
> +
> +       msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
> +       /*
> +        * Initialize and add the meta parameters needed when opening a
> +        * session.
> +        */
> +       msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
> +                                 OPTEE_MSG_ATTR_META;
> +       msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
> +                                 OPTEE_MSG_ATTR_META;
> +       memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
> +       memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
> +       msg_arg->params[1].u.value.c = arg->clnt_login;
> +
> +       rc = to_msg_param(msg_arg->params + 2, num_params, params);
> +       if (rc)
> +               goto out;
> +
> +       arg->ret = do_call_with_arg(dev, msg_arg);
> +       if (arg->ret) {
> +               arg->ret_origin = TEE_ORIGIN_COMMS;
> +               goto out;
> +       }
> +
> +       if (from_msg_param(params, num_params, msg_arg->params + 2)) {
> +               arg->ret = TEE_ERROR_COMMUNICATION;
> +               arg->ret_origin = TEE_ORIGIN_COMMS;
> +               /* Close session again to avoid leakage */
> +               optee_close_session(dev, msg_arg->session);
> +               goto out;
> +       }
> +
> +       arg->session = msg_arg->session;
> +       arg->ret = msg_arg->ret;
> +       arg->ret_origin = msg_arg->ret_origin;
> +out:
> +       tee_shm_free(shm);
> +
> +       return rc;
> +}
> +
> +int optee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                     ulong num_params, struct tee_param *params)
> +{
> +       struct tee_shm *shm;
> +       struct optee_msg_arg *msg_arg;
> +       int rc;
> +
> +       shm = get_msg_arg(dev, num_params, &msg_arg);
> +       if (!shm)
> +               return -ENOMEM;
> +       msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
> +       msg_arg->func = arg->func;
> +       msg_arg->session = arg->session;
> +
> +       rc = to_msg_param(msg_arg->params, num_params, params);
> +       if (rc)
> +               goto out;
> +
> +       arg->ret = do_call_with_arg(dev, msg_arg);
> +       if (arg->ret) {
> +               arg->ret_origin = TEE_ORIGIN_COMMS;
> +               goto out;
> +       }
> +
> +       if (from_msg_param(params, num_params, msg_arg->params)) {
> +               arg->ret = TEE_ERROR_COMMUNICATION;
> +               arg->ret_origin = TEE_ORIGIN_COMMS;
> +               goto out;
> +       }
> +
> +       arg->ret = msg_arg->ret;
> +       arg->ret_origin = msg_arg->ret_origin;
> +out:
> +       tee_shm_free(shm);
> +       return rc;
> +}
> +
> +int optee_shm_register(struct udevice *dev, struct tee_shm *shm)
> +{
> +       struct tee_shm *shm_arg;
> +       struct optee_msg_arg *msg_arg;
> +       void *pl;
> +       u64 ph_ptr;
> +       int rc = 0;
> +
> +       shm_arg = get_msg_arg(dev, 1, &msg_arg);
> +       if (!shm_arg)
> +               return -ENOMEM;
> +
> +       pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr);
> +       if (!pl) {
> +               rc = -ENOMEM;
> +               goto out;
> +       }
> +
> +       msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM;
> +       msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
> +                               OPTEE_MSG_ATTR_NONCONTIG;
> +       msg_arg->params->u.tmem.buf_ptr = ph_ptr;
> +       msg_arg->params->u.tmem.shm_ref = (ulong)shm;
> +       msg_arg->params->u.tmem.size = shm->size;
> +
> +       if (do_call_with_arg(dev, msg_arg) || msg_arg->ret)
> +               rc = -EINVAL;
> +
> +       free(pl);
> +out:
> +       tee_shm_free(shm_arg);
> +       return rc;
> +}
> +
> +int optee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
> +{
> +       struct tee_shm *shm_arg;
> +       struct optee_msg_arg *msg_arg;
> +       int rc = 0;
> +
> +       shm_arg = get_msg_arg(dev, 1, &msg_arg);
> +       if (!shm_arg)
> +               return -ENOMEM;
> +
> +       msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
> +       msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
> +       msg_arg->params[0].u.rmem.shm_ref = (ulong)shm;
> +
> +       if (do_call_with_arg(dev, msg_arg) || msg_arg->ret)
> +               rc = -EINVAL;
> +       tee_shm_free(shm_arg);
> +       return rc;
> +}
> +
> +static const struct tee_driver_ops optee_ops = {
> +       .get_version = optee_get_version,
> +       .open_session = optee_open_session,
> +       .close_session = optee_close_session,
> +       .invoke_func = optee_invoke_func,
> +       .shm_register = optee_shm_register,
> +       .shm_unregister = optee_shm_unregister,
> +};
> +
> +static bool is_optee_api(optee_invoke_fn *invoke_fn)
> +{
> +       struct arm_smccc_res res;
> +
> +       invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
> +
> +       return res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
> +              res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3;
> +}
> +
> +static void print_os_revision(optee_invoke_fn *invoke_fn)
> +{
> +       union {
> +               struct arm_smccc_res smccc;
> +               struct optee_smc_call_get_os_revision_result result;
> +       } res = {
> +               .result = {
> +               .build_id = 0
> +               }
> +       };
> +
> +       invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
> +                 &res.smccc);
> +
> +       if (res.result.build_id)
> +               debug("OP-TEE revision %lu.%lu (%08lx)\n", res.result.major,
> +                     res.result.minor, res.result.build_id);
> +       else
> +               debug("OP-TEE revision %lu.%lu\n", res.result.major,
> +                     res.result.minor);
> +}
> +
> +static bool api_revision_is_compatible(optee_invoke_fn *invoke_fn)
> +{
> +       union {
> +               struct arm_smccc_res smccc;
> +               struct optee_smc_calls_revision_result result;
> +       } res;
> +
> +       invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
> +
> +       return res.result.major == OPTEE_MSG_REVISION_MAJOR &&
> +              (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR;
> +}
> +
> +static bool exchange_capabilities(optee_invoke_fn *invoke_fn, u32 *sec_caps)
> +{
> +       union {
> +               struct arm_smccc_res smccc;
> +               struct optee_smc_exchange_capabilities_result result;
> +       } res;
> +
> +       invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES,
> +                 OPTEE_SMC_NSEC_CAP_UNIPROCESSOR, 0, 0, 0, 0, 0, 0,
> +                 &res.smccc);
> +
> +       if (res.result.status != OPTEE_SMC_RETURN_OK)
> +               return false;
> +
> +       *sec_caps = res.result.capabilities;
> +       return true;
> +}
> +
> +/* Simple wrapper functions to be able to use a function pointer */
> +static void optee_smccc_smc(unsigned long a0, unsigned long a1,
> +                           unsigned long a2, unsigned long a3,
> +                           unsigned long a4, unsigned long a5,
> +                           unsigned long a6, unsigned long a7,
> +                           struct arm_smccc_res *res)
> +{
> +       arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
> +}
> +
> +static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
> +                           unsigned long a2, unsigned long a3,
> +                           unsigned long a4, unsigned long a5,
> +                           unsigned long a6, unsigned long a7,
> +                           struct arm_smccc_res *res)
> +{
> +       arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
> +}
> +
> +static optee_invoke_fn *get_invoke_func(struct udevice *dev)
> +{
> +       const char *method;
> +
> +       debug("optee: looking for conduit method in DT.\n");
> +       method = ofnode_get_property(dev->node, "method", NULL);
> +       if (!method) {
> +               debug("optee: missing \"method\" property\n");
> +               return ERR_PTR(-ENXIO);
> +       }
> +
> +       if (!strcmp("hvc", method))
> +               return optee_smccc_hvc;
> +       else if (!strcmp("smc", method))
> +               return optee_smccc_smc;
> +
> +       debug("optee: invalid \"method\" property: %s\n", method);
> +       return ERR_PTR(-EINVAL);
> +}
> +
> +static int optee_ofdata_to_platdata(struct udevice *dev)
> +{
> +       struct optee_pdata *pdata = dev_get_platdata(dev);
> +
> +       pdata->invoke_fn = get_invoke_func(dev);
> +       if (IS_ERR(pdata->invoke_fn))
> +               return PTR_ERR(pdata->invoke_fn);
> +
> +       return 0;
> +}
> +
> +static int optee_probe(struct udevice *dev)
> +{
> +       struct optee_pdata *pdata = dev_get_platdata(dev);
> +       u32 sec_caps;
> +
> +       if (!is_optee_api(pdata->invoke_fn)) {
> +               debug("%s: OP-TEE api uid mismatch\n", __func__);
> +               return -ENOENT;
> +       }
> +
> +       print_os_revision(pdata->invoke_fn);
> +
> +       if (!api_revision_is_compatible(pdata->invoke_fn)) {
> +               debug("%s: OP-TEE api revision mismatch\n", __func__);
> +               return -ENOENT;
> +       }
> +
> +       /*
> +        * OP-TEE can use both shared memory via predefined pool or as
> +        * dynamic shared memory provided by normal world. To keep things
> +        * simple we're only using dynamic shared memory in this driver.
> +        */
> +       if (!exchange_capabilities(pdata->invoke_fn, &sec_caps) ||
> +           !(sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)) {
> +               debug("%s: OP-TEE capabilities mismatch\n", __func__);
> +               return -ENOENT;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id optee_match[] = {
> +       { .compatible = "linaro,optee-tz" },
> +       {},
> +};
> +
> +U_BOOT_DRIVER(optee) = {
> +       .name = "optee",
> +       .id = UCLASS_TEE,
> +       .of_match = optee_match,
> +       .ofdata_to_platdata = optee_ofdata_to_platdata,
> +       .probe = optee_probe,
> +       .ops = &optee_ops,
> +       .platdata_auto_alloc_size = sizeof(struct optee_pdata),
> +};
> diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
> new file mode 100644
> index 000000000000..ebc16aa8cc31
> --- /dev/null
> +++ b/drivers/tee/optee/optee_msg.h
> @@ -0,0 +1,423 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Copyright (c) 2015-2018, Linaro Limited
> + */
> +
> +#ifndef _OPTEE_MSG_H
> +#define _OPTEE_MSG_H
> +
> +#include <linux/bitops.h>
> +#include <linux/types.h>
> +
> +/*
> + * This file defines the OP-TEE message protocol used to communicate
> + * with an instance of OP-TEE running in secure world.
> + *
> + * This file is divided into three sections.
> + * 1. Formatting of messages.
> + * 2. Requests from normal world
> + * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
> + *    tee-supplicant.
> + */
> +
> +/*****************************************************************************
> + * Part 1 - formatting of messages
> + *****************************************************************************/
> +
> +#define OPTEE_MSG_ATTR_TYPE_NONE               0x0
> +#define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT                0x1
> +#define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT       0x2
> +#define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT                0x3
> +#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT         0x5
> +#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT                0x6
> +#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT         0x7
> +#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT         0x9
> +#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT                0xa
> +#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT         0xb
> +
> +#define OPTEE_MSG_ATTR_TYPE_MASK               GENMASK(7, 0)
> +
> +/*
> + * Meta parameter to be absorbed by the Secure OS and not passed
> + * to the Trusted Application.
> + *
> + * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION.
> + */
> +#define OPTEE_MSG_ATTR_META                    BIT(8)
> +
> +/*
> + * Pointer to a list of pages used to register user-defined SHM buffer.
> + * Used with OPTEE_MSG_ATTR_TYPE_TMEM_*.
> + * buf_ptr should point to the beginning of the buffer. Buffer will contain
> + * list of page addresses. OP-TEE core can reconstruct contiguous buffer from
> + * that page addresses list. Page addresses are stored as 64 bit values.
> + * Last entry on a page should point to the next page of buffer.
> + * Every entry in buffer should point to a 4k page beginning (12 least
> + * significant bits must be equal to zero).
> + *
> + * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
> + * offset of the user buffer.
> + *
> + * So, entries should be placed like members of this structure:
> + *
> + * struct page_data {
> + *   uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1];
> + *   uint64_t next_page_data;
> + * };
> + *
> + * Structure is designed to exactly fit into the page size
> + * OPTEE_MSG_NONCONTIG_PAGE_SIZE which is a standard 4KB page.
> + *
> + * The size of 4KB is chosen because this is the smallest page size for ARM
> + * architectures. If REE uses larger pages, it should divide them to 4KB ones.
> + */
> +#define OPTEE_MSG_ATTR_NONCONTIG               BIT(9)
> +
> +/*
> + * Memory attributes for caching passed with temp memrefs. The actual value
> + * used is defined outside the message protocol with the exception of
> + * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already
> + * defined for the memory range should be used. If optee_smc.h is used as
> + * bearer of this protocol OPTEE_SMC_SHM_* is used for values.
> + */
> +#define OPTEE_MSG_ATTR_CACHE_SHIFT             16
> +#define OPTEE_MSG_ATTR_CACHE_MASK              GENMASK(2, 0)
> +#define OPTEE_MSG_ATTR_CACHE_PREDEFINED                0
> +
> +/*
> + * Same values as TEE_LOGIN_* from TEE Internal API
> + */
> +#define OPTEE_MSG_LOGIN_PUBLIC                 0x00000000
> +#define OPTEE_MSG_LOGIN_USER                   0x00000001
> +#define OPTEE_MSG_LOGIN_GROUP                  0x00000002
> +#define OPTEE_MSG_LOGIN_APPLICATION            0x00000004
> +#define OPTEE_MSG_LOGIN_APPLICATION_USER       0x00000005
> +#define OPTEE_MSG_LOGIN_APPLICATION_GROUP      0x00000006
> +
> +/*
> + * Page size used in non-contiguous buffer entries
> + */
> +#define OPTEE_MSG_NONCONTIG_PAGE_SIZE          4096
> +
> +/**
> + * struct optee_msg_param_tmem - temporary memory reference parameter
> + * @buf_ptr:   Address of the buffer
> + * @size:      Size of the buffer
> + * @shm_ref:   Temporary shared memory reference, pointer to a struct tee_shm
> + *
> + * Secure and normal world communicates pointers as physical address
> + * instead of the virtual address. This is because secure and normal world
> + * have completely independent memory mapping. Normal world can even have a
> + * hypervisor which need to translate the guest physical address (AKA IPA
> + * in ARM documentation) to a real physical address before passing the
> + * structure to secure world.
> + */
> +struct optee_msg_param_tmem {
> +       u64 buf_ptr;
> +       u64 size;
> +       u64 shm_ref;
> +};
> +
> +/**
> + * struct optee_msg_param_rmem - registered memory reference parameter
> + * @offs:      Offset into shared memory reference
> + * @size:      Size of the buffer
> + * @shm_ref:   Shared memory reference, pointer to a struct tee_shm
> + */
> +struct optee_msg_param_rmem {
> +       u64 offs;
> +       u64 size;
> +       u64 shm_ref;
> +};
> +
> +/**
> + * struct optee_msg_param_value - opaque value parameter
> + *
> + * Value parameters are passed unchecked between normal and secure world.
> + */
> +struct optee_msg_param_value {
> +       u64 a;
> +       u64 b;
> +       u64 c;
> +};
> +
> +/**
> + * struct optee_msg_param - parameter used together with struct optee_msg_arg
> + * @attr:      attributes
> + * @tmem:      parameter by temporary memory reference
> + * @rmem:      parameter by registered memory reference
> + * @value:     parameter by opaque value
> + *
> + * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
> + * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
> + * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
> + * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
> + * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
> + */
> +struct optee_msg_param {
> +       u64 attr;
> +       union {
> +               struct optee_msg_param_tmem tmem;
> +               struct optee_msg_param_rmem rmem;
> +               struct optee_msg_param_value value;
> +       } u;
> +};
> +
> +/**
> + * struct optee_msg_arg - call argument
> + * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_*
> + * @func: Trusted Application function, specific to the Trusted Application,
> + *          used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND
> + * @session: In parameter for all OPTEE_MSG_CMD_* except
> + *          OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead
> + * @cancel_id: Cancellation id, a unique value to identify this request
> + * @ret: return value
> + * @ret_origin: origin of the return value
> + * @num_params: number of parameters supplied to the OS Command
> + * @params: the parameters supplied to the OS Command
> + *
> + * All normal calls to Trusted OS uses this struct. If cmd requires further
> + * information than what these field holds it can be passed as a parameter
> + * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
> + * attrs field). All parameters tagged as meta has to come first.
> + *
> + * Temp memref parameters can be fragmented if supported by the Trusted OS
> + * (when optee_smc.h is bearer of this protocol this is indicated with
> + * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
> + * fragmented then has all but the last fragment the
> + * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
> + * it will still be presented as a single logical memref to the Trusted
> + * Application.
> + */
> +struct optee_msg_arg {
> +       u32 cmd;
> +       u32 func;
> +       u32 session;
> +       u32 cancel_id;
> +       u32 pad;
> +       u32 ret;
> +       u32 ret_origin;
> +       u32 num_params;
> +
> +       /* num_params tells the actual number of element in params */
> +       struct optee_msg_param params[0];
> +};
> +
> +/**
> + * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg
> + *
> + * @num_params: Number of parameters embedded in the struct optee_msg_arg
> + *
> + * Returns the size of the struct optee_msg_arg together with the number
> + * of embedded parameters.
> + */
> +#define OPTEE_MSG_GET_ARG_SIZE(num_params) \
> +       (sizeof(struct optee_msg_arg) + \
> +        sizeof(struct optee_msg_param) * (num_params))
> +
> +/*****************************************************************************
> + * Part 2 - requests from normal world
> + *****************************************************************************/
> +
> +/*
> + * Return the following UID if using API specified in this file without
> + * further extensions:
> + * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
> + * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
> + * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
> + */
> +#define OPTEE_MSG_UID_0                        0x384fb3e0
> +#define OPTEE_MSG_UID_1                        0xe7f811e3
> +#define OPTEE_MSG_UID_2                        0xaf630002
> +#define OPTEE_MSG_UID_3                        0xa5d5c51b
> +#define OPTEE_MSG_FUNCID_CALLS_UID     0xFF01
> +
> +/*
> + * Returns 2.0 if using API specified in this file without further
> + * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR
> + * and OPTEE_MSG_REVISION_MINOR
> + */
> +#define OPTEE_MSG_REVISION_MAJOR       2
> +#define OPTEE_MSG_REVISION_MINOR       0
> +#define OPTEE_MSG_FUNCID_CALLS_REVISION        0xFF03
> +
> +/*
> + * Get UUID of Trusted OS.
> + *
> + * Used by non-secure world to figure out which Trusted OS is installed.
> + * Note that returned UUID is the UUID of the Trusted OS, not of the API.
> + *
> + * Returns UUID in 4 32-bit words in the same way as
> + * OPTEE_MSG_FUNCID_CALLS_UID described above.
> + */
> +#define OPTEE_MSG_OS_OPTEE_UUID_0      0x486178e0
> +#define OPTEE_MSG_OS_OPTEE_UUID_1      0xe7f811e3
> +#define OPTEE_MSG_OS_OPTEE_UUID_2      0xbc5e0002
> +#define OPTEE_MSG_OS_OPTEE_UUID_3      0xa5d5c51b
> +#define OPTEE_MSG_FUNCID_GET_OS_UUID   0x0000
> +
> +/*
> + * Get revision of Trusted OS.
> + *
> + * Used by non-secure world to figure out which version of the Trusted OS
> + * is installed. Note that the returned revision is the revision of the
> + * Trusted OS, not of the API.
> + *
> + * Returns revision in 2 32-bit words in the same way as
> + * OPTEE_MSG_CALLS_REVISION described above.
> + */
> +#define OPTEE_MSG_FUNCID_GET_OS_REVISION       0x0001
> +
> +/*
> + * Do a secure call with struct optee_msg_arg as argument
> + * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
> + *
> + * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application.
> + * The first two parameters are tagged as meta, holding two value
> + * parameters to pass the following information:
> + * param[0].u.value.a-b uuid of Trusted Application
> + * param[1].u.value.a-b uuid of Client
> + * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_*
> + *
> + * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened
> + * session to a Trusted Application.  struct optee_msg_arg::func is Trusted
> + * Application function, specific to the Trusted Application.
> + *
> + * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to
> + * Trusted Application.
> + *
> + * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command.
> + *
> + * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
> + * information is passed as:
> + * [in] param[0].attr                  OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
> + *                                     [| OPTEE_MSG_ATTR_FRAGMENT]
> + * [in] param[0].u.tmem.buf_ptr                physical address (of first fragment)
> + * [in] param[0].u.tmem.size           size (of first fragment)
> + * [in] param[0].u.tmem.shm_ref                holds shared memory reference
> + * ...
> + * The shared memory can optionally be fragmented, temp memrefs can follow
> + * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
> + *
> + * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
> + * memory reference. The information is passed as:
> + * [in] param[0].attr                  OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
> + * [in] param[0].u.rmem.shm_ref                holds shared memory reference
> + * [in] param[0].u.rmem.offs           0
> + * [in] param[0].u.rmem.size           0
> + */
> +#define OPTEE_MSG_CMD_OPEN_SESSION     0
> +#define OPTEE_MSG_CMD_INVOKE_COMMAND   1
> +#define OPTEE_MSG_CMD_CLOSE_SESSION    2
> +#define OPTEE_MSG_CMD_CANCEL           3
> +#define OPTEE_MSG_CMD_REGISTER_SHM     4
> +#define OPTEE_MSG_CMD_UNREGISTER_SHM   5
> +#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
> +
> +/*****************************************************************************
> + * Part 3 - Requests from secure world, RPC
> + *****************************************************************************/
> +
> +/*
> + * All RPC is done with a struct optee_msg_arg as bearer of information,
> + * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
> + *
> + * RPC communication with tee-supplicant is reversed compared to normal
> + * client communication desribed above. The supplicant receives requests
> + * and sends responses.
> + */
> +
> +/*
> + * Load a TA into memory, defined in tee-supplicant
> + */
> +#define OPTEE_MSG_RPC_CMD_LOAD_TA      0
> +
> +/*
> + * Reserved
> + */
> +#define OPTEE_MSG_RPC_CMD_RPMB         1
> +
> +/*
> + * File system access, defined in tee-supplicant
> + */
> +#define OPTEE_MSG_RPC_CMD_FS           2
> +
> +/*
> + * Get time
> + *
> + * Returns number of seconds and nano seconds since the Epoch,
> + * 1970-01-01 00:00:00 +0000 (UTC).
> + *
> + * [out] param[0].u.value.a    Number of seconds
> + * [out] param[0].u.value.b    Number of nano seconds.
> + */
> +#define OPTEE_MSG_RPC_CMD_GET_TIME     3
> +
> +/*
> + * Wait queue primitive, helper for secure world to implement a wait queue.
> + *
> + * If secure world need to wait for a secure world mutex it issues a sleep
> + * request instead of spinning in secure world. Conversely is a wakeup
> + * request issued when a secure world mutex with a thread waiting thread is
> + * unlocked.
> + *
> + * Waiting on a key
> + * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
> + * [in] param[0].u.value.b wait key
> + *
> + * Waking up a key
> + * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
> + * [in] param[0].u.value.b wakeup key
> + */
> +#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE   4
> +#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
> +#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP        1
> +
> +/*
> + * Suspend execution
> + *
> + * [in] param[0].value .a number of milliseconds to suspend
> + */
> +#define OPTEE_MSG_RPC_CMD_SUSPEND      5
> +
> +/*
> + * Allocate a piece of shared memory
> + *
> + * Shared memory can optionally be fragmented, to support that additional
> + * spare param entries are allocated to make room for eventual fragments.
> + * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
> + * unused. All returned temp memrefs except the last should have the
> + * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
> + *
> + * [in]  param[0].u.value.a            type of memory one of
> + *                                     OPTEE_MSG_RPC_SHM_TYPE_* below
> + * [in]  param[0].u.value.b            requested size
> + * [in]  param[0].u.value.c            required alignment
> + *
> + * [out] param[0].u.tmem.buf_ptr       physical address (of first fragment)
> + * [out] param[0].u.tmem.size          size (of first fragment)
> + * [out] param[0].u.tmem.shm_ref       shared memory reference
> + * ...
> + * [out] param[n].u.tmem.buf_ptr       physical address
> + * [out] param[n].u.tmem.size          size
> + * [out] param[n].u.tmem.shm_ref       shared memory reference (same value
> + *                                     as in param[n-1].u.tmem.shm_ref)
> + */
> +#define OPTEE_MSG_RPC_CMD_SHM_ALLOC    6
> +/* Memory that can be shared with a non-secure user space application */
> +#define OPTEE_MSG_RPC_SHM_TYPE_APPL    0
> +/* Memory only shared with non-secure kernel */
> +#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL  1
> +
> +/*
> + * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
> + *
> + * [in]  param[0].u.value.a            type of memory one of
> + *                                     OPTEE_MSG_RPC_SHM_TYPE_* above
> + * [in]  param[0].u.value.b            value of shared memory reference
> + *                                     returned in param[0].u.tmem.shm_ref
> + *                                     above
> + */
> +#define OPTEE_MSG_RPC_CMD_SHM_FREE     7
> +
> +#endif /* _OPTEE_MSG_H */
> diff --git a/drivers/tee/optee/optee_msg_supplicant.h b/drivers/tee/optee/optee_msg_supplicant.h
> new file mode 100644
> index 000000000000..65ca6c0574b9
> --- /dev/null
> +++ b/drivers/tee/optee/optee_msg_supplicant.h
> @@ -0,0 +1,234 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Copyright (c) 2016-2018, Linaro Limited
> + */
> +
> +#ifndef __OPTEE_MSG_SUPPLICANT_H
> +#define __OPTEE_MSG_SUPPLICANT_H
> +
> +/*
> + * Load a TA into memory
> + */
> +#define OPTEE_MSG_RPC_CMD_LOAD_TA      0
> +
> +/*
> + * Replay Protected Memory Block access
> + */
> +#define OPTEE_MSG_RPC_CMD_RPMB         1
> +
> +/*
> + * File system access
> + */
> +#define OPTEE_MSG_RPC_CMD_FS           2
> +
> +/*
> + * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_FS and first
> + * parameter has the attribute OPTEE_MSG_ATTR_TYPE_VALUE_INPUT.
> + */
> +
> +/*
> + * Open a file
> + *
> + * [in]     param[0].u.value.a OPTEE_MRF_OPEN
> + * [in]     param[1].u.tmem    a string holding the file name
> + * [out]    param[2].u.value.a file descriptor of open file
> + */
> +#define OPTEE_MRF_OPEN                 0
> +
> +/*
> + * Create a file
> + *
> + * [in]     param[0].u.value.a OPTEE_MRF_CREATE
> + * [in]     param[1].u.tmem    a string holding the file name
> + * [out]    param[2].u.value.a file descriptor of open file
> + */
> +#define OPTEE_MRF_CREATE               1
> +
> +/*
> + * Close a file
> + *
> + * [in]     param[0].u.value.a OPTEE_MRF_CLOSE
> + * [in]     param[0].u.value.b file descriptor of open file.
> + */
> +#define OPTEE_MRF_CLOSE                        2
> +
> +/*
> + * Read from a file
> + *
> + * [in]     param[0].u.value.a OPTEE_MRF_READ
> + * [in]     param[0].u.value.b file descriptor of open file
> + * [in]     param[0].u.value.c offset into file
> + * [out]    param[1].u.tmem    buffer to hold returned data
> + */
> +#define OPTEE_MRF_READ                 3
> +
> +/*
> + * Write to a file
> + *
> + * [in]     param[0].u.value.a OPTEE_MRF_WRITE
> + * [in]     param[0].u.value.b file descriptor of open file
> + * [in]     param[0].u.value.c offset into file
> + * [in]     param[1].u.tmem    buffer holding data to be written
> + */
> +#define OPTEE_MRF_WRITE                        4
> +
> +/*
> + * Truncate a file
> + *
> + * [in]     param[0].u.value.a OPTEE_MRF_TRUNCATE
> + * [in]     param[0].u.value.b file descriptor of open file
> + * [in]     param[0].u.value.c length of file.
> + */
> +#define OPTEE_MRF_TRUNCATE             5
> +
> +/*
> + * Remove a file
> + *
> + * [in]  param[0].u.value.a    OPTEE_MRF_REMOVE
> + * [in]  param[1].u.tmem       a string holding the file name
> + */
> +#define OPTEE_MRF_REMOVE               6
> +
> +/*
> + * Rename a file
> + *
> + * [in]  param[0].u.value.a    OPTEE_MRF_RENAME
> + * [in]  param[0].u.value.b    true if existing target should be removed
> + * [in]  param[1].u.tmem       a string holding the old file name
> + * [in]  param[2].u.tmem       a string holding the new file name
> + */
> +#define OPTEE_MRF_RENAME               7
> +
> +/*
> + * Opens a directory for file listing
> + *
> + * [in]  param[0].u.value.a    OPTEE_MRF_OPENDIR
> + * [in]  param[1].u.tmem       a string holding the name of the directory
> + * [out] param[2].u.value.a    handle to open directory
> + */
> +#define OPTEE_MRF_OPENDIR              8
> +
> +/*
> + * Closes a directory handle
> + *
> + * [in]  param[0].u.value.a    OPTEE_MRF_CLOSEDIR
> + * [in]  param[0].u.value.b    handle to open directory
> + */
> +#define OPTEE_MRF_CLOSEDIR             9
> +
> +/*
> + * Read next file name of directory
> + *
> + *
> + * [in]  param[0].u.value.a    OPTEE_MRF_READDIR
> + * [in]  param[0].u.value.b    handle to open directory
> + * [out] param[1].u.tmem       a string holding the file name
> + */
> +#define OPTEE_MRF_READDIR              10
> +
> +/*
> + * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_FS
> + */
> +
> +/*
> + * Command Ids 3, 4 and 5 of OPTEE_MSG_RPC_CMD_xxx macros are reserved for use
> + * by the kernel driver.
> + */
> +
> +/*
> + * Shared memory allocation
> + */
> +#define OPTEE_MSG_RPC_CMD_SHM_ALLOC    6
> +#define OPTEE_MSG_RPC_CMD_SHM_FREE     7
> +
> +/*
> + * Was OPTEE_MSG_RPC_CMD_SQL_FS, which isn't supported any longer
> + */
> +#define OPTEE_MSG_RPC_CMD_SQL_FS_RESERVED      8
> +
> +/*
> + * GPROF support management commands
> + */
> +#define OPTEE_MSG_RPC_CMD_GPROF                9
> +
> +/*
> + * Socket commands
> + */
> +#define OPTEE_MSG_RPC_CMD_SOCKET       10
> +
> +/*
> + * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET
> + */
> +
> +#define OPTEE_MRC_SOCKET_TIMEOUT_NONBLOCKING   0
> +#define OPTEE_MRC_SOCKET_TIMEOUT_BLOCKING      0xffffffff
> +
> +/*
> + * Open socket
> + *
> + * [in]     param[0].u.value.a OPTEE_MRC_SOCKET_OPEN
> + * [in]     param[0].u.value.b TA instance id
> + * [in]     param[1].u.value.a server port number
> + * [in]     param[1].u.value.b protocol, TEE_ISOCKET_PROTOCOLID_*
> + * [in]     param[1].u.value.c ip version TEE_IP_VERSION_* from tee_ipsocket.h
> + * [in]     param[2].u.tmem    server address
> + * [out]    param[3].u.value.a socket handle (32-bit)
> + */
> +#define OPTEE_MRC_SOCKET_OPEN  0
> +
> +/*
> + * Close socket
> + *
> + * [in]     param[0].u.value.a OPTEE_MRC_SOCKET_CLOSE
> + * [in]     param[0].u.value.b TA instance id
> + * [in]     param[0].u.value.c socket handle
> + */
> +#define OPTEE_MRC_SOCKET_CLOSE 1
> +
> +/*
> + * Close all sockets
> + *
> + * [in]     param[0].u.value.a OPTEE_MRC_SOCKET_CLOSE_ALL
> + * [in]     param[0].u.value.b TA instance id
> + */
> +#define OPTEE_MRC_SOCKET_CLOSE_ALL 2
> +
> +/*
> + * Send data on socket
> + *
> + * [in]     param[0].u.value.a OPTEE_MRC_SOCKET_SEND
> + * [in]     param[0].u.value.b TA instance id
> + * [in]     param[0].u.value.c socket handle
> + * [in]     param[1].u.tmem    buffer to transmit
> + * [in]     param[2].u.value.a timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_*
> + * [out]    param[2].u.value.b number of transmitted bytes
> + */
> +#define OPTEE_MRC_SOCKET_SEND  3
> +
> +/*
> + * Receive data on socket
> + *
> + * [in]     param[0].u.value.a OPTEE_MRC_SOCKET_RECV
> + * [in]     param[0].u.value.b TA instance id
> + * [in]     param[0].u.value.c socket handle
> + * [out]    param[1].u.tmem    buffer to receive
> + * [in]     param[2].u.value.a timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_*
> + */
> +#define OPTEE_MRC_SOCKET_RECV  4
> +
> +/*
> + * Perform IOCTL on socket
> + *
> + * [in]     param[0].u.value.a OPTEE_MRC_SOCKET_IOCTL
> + * [in]     param[0].u.value.b TA instance id
> + * [in]     param[0].u.value.c socket handle
> + * [in/out] param[1].u.tmem    buffer
> + * [in]     param[2].u.value.a ioctl command
> + */
> +#define OPTEE_MRC_SOCKET_IOCTL 5
> +
> +/*
> + * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET
> + */
> +
> +#endif /*__OPTEE_MSG_SUPPLICANT_H*/
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> new file mode 100644
> index 000000000000..daa470f812a9
> --- /dev/null
> +++ b/drivers/tee/optee/optee_private.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#ifndef __OPTEE_PRIVATE_H
> +#define __OPTEE_PRIVATE_H
> +
> +void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr);
> +void optee_suppl_cmd(struct udevice *dev, void *shm, void **page_list);
> +
> +#endif /*__OPTEE_PRIVATE_H*/
> diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
> new file mode 100644
> index 000000000000..81069ae6f8ac
> --- /dev/null
> +++ b/drivers/tee/optee/optee_smc.h
> @@ -0,0 +1,444 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/*
> + * Copyright (c) 2015-2018, Linaro Limited
> + */
> +
> +#ifndef OPTEE_SMC_H
> +#define OPTEE_SMC_H
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/bitops.h>
> +
> +#define OPTEE_SMC_STD_CALL_VAL(func_num) \
> +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
> +                          ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
> +#define OPTEE_SMC_FAST_CALL_VAL(func_num) \
> +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
> +                          ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
> +
> +/*
> + * Function specified by SMC Calling convention.
> + */
> +#define OPTEE_SMC_FUNCID_CALLS_COUNT   0xFF00
> +#define OPTEE_SMC_CALLS_COUNT \
> +       ARM_SMCCC_CALL_VAL(OPTEE_SMC_FAST_CALL, SMCCC_SMC_32, \
> +                          SMCCC_OWNER_TRUSTED_OS_END, \
> +                          OPTEE_SMC_FUNCID_CALLS_COUNT)
> +
> +/*
> + * Normal cached memory (write-back), shareable for SMP systems and not
> + * shareable for UP systems.
> + */
> +#define OPTEE_SMC_SHM_CACHED           1
> +
> +/*
> + * a0..a7 is used as register names in the descriptions below, on arm32
> + * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's
> + * 32-bit registers.
> + */
> +
> +/*
> + * Function specified by SMC Calling convention
> + *
> + * Return one of the following UIDs if using API specified in this file
> + * without further extentions:
> + * 65cb6b93-af0c-4617-8ed6-644a8d1140f8
> + * see also OPTEE_SMC_UID_* in optee_msg.h
> + */
> +#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
> +#define OPTEE_SMC_CALLS_UID \
> +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
> +                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
> +                          OPTEE_SMC_FUNCID_CALLS_UID)
> +
> +/*
> + * Function specified by SMC Calling convention
> + *
> + * Returns 2.0 if using API specified in this file without further extentions.
> + * see also OPTEE_MSG_REVISION_* in optee_msg.h
> + */
> +#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
> +#define OPTEE_SMC_CALLS_REVISION \
> +       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
> +                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
> +                          OPTEE_SMC_FUNCID_CALLS_REVISION)
> +
> +struct optee_smc_calls_revision_result {
> +       unsigned long major;
> +       unsigned long minor;
> +       unsigned long reserved0;
> +       unsigned long reserved1;
> +};
> +
> +/*
> + * Get UUID of Trusted OS.
> + *
> + * Used by non-secure world to figure out which Trusted OS is installed.
> + * Note that returned UUID is the UUID of the Trusted OS, not of the API.
> + *
> + * Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID
> + * described above.
> + */
> +#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID
> +#define OPTEE_SMC_CALL_GET_OS_UUID \
> +       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID)
> +
> +/*
> + * Get revision of Trusted OS.
> + *
> + * Used by non-secure world to figure out which version of the Trusted OS
> + * is installed. Note that the returned revision is the revision of the
> + * Trusted OS, not of the API.
> + *
> + * Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION
> + * described above. May optionally return a 32-bit build identifier in a2,
> + * with zero meaning unspecified.
> + */
> +#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION
> +#define OPTEE_SMC_CALL_GET_OS_REVISION \
> +       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION)
> +
> +struct optee_smc_call_get_os_revision_result {
> +       unsigned long major;
> +       unsigned long minor;
> +       unsigned long build_id;
> +       unsigned long reserved1;
> +};
> +
> +/*
> + * Call with struct optee_msg_arg as argument
> + *
> + * Call register usage:
> + * a0  SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
> + * a1  Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
> + * a2  Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
> + * a3  Cache settings, not used if physical pointer is in a predefined shared
> + *     memory area else per OPTEE_SMC_SHM_*
> + * a4-6        Not used
> + * a7  Hypervisor Client ID register
> + *
> + * Normal return register usage:
> + * a0  Return value, OPTEE_SMC_RETURN_*
> + * a1-3        Not used
> + * a4-7        Preserved
> + *
> + * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage:
> + * a0  Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT
> + * a1-3        Preserved
> + * a4-7        Preserved
> + *
> + * RPC return register usage:
> + * a0  Return value, OPTEE_SMC_RETURN_IS_RPC(val)
> + * a1-2        RPC parameters
> + * a3-7        Resume information, must be preserved
> + *
> + * Possible return values:
> + * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION   Trusted OS does not recognize this
> + *                                     function.
> + * OPTEE_SMC_RETURN_OK                 Call completed, result updated in
> + *                                     the previously supplied struct
> + *                                     optee_msg_arg.
> + * OPTEE_SMC_RETURN_ETHREAD_LIMIT      Number of Trusted OS threads exceeded,
> + *                                     try again later.
> + * OPTEE_SMC_RETURN_EBADADDR           Bad physcial pointer to struct
> + *                                     optee_msg_arg.
> + * OPTEE_SMC_RETURN_EBADCMD            Bad/unknown cmd in struct optee_msg_arg
> + * OPTEE_SMC_RETURN_IS_RPC()           Call suspended by RPC call to normal
> + *                                     world.
> + */
> +#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG
> +#define OPTEE_SMC_CALL_WITH_ARG \
> +       OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG)
> +
> +/*
> + * Get Shared Memory Config
> + *
> + * Returns the Secure/Non-secure shared memory config.
> + *
> + * Call register usage:
> + * a0  SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG
> + * a1-6        Not used
> + * a7  Hypervisor Client ID register
> + *
> + * Have config return register usage:
> + * a0  OPTEE_SMC_RETURN_OK
> + * a1  Physical address of start of SHM
> + * a2  Size of of SHM
> + * a3  Cache settings of memory, as defined by the
> + *     OPTEE_SMC_SHM_* values above
> + * a4-7        Preserved
> + *
> + * Not available register usage:
> + * a0  OPTEE_SMC_RETURN_ENOTAVAIL
> + * a1-3 Not used
> + * a4-7        Preserved
> + */
> +#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG        7
> +#define OPTEE_SMC_GET_SHM_CONFIG \
> +       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG)
> +
> +struct optee_smc_get_shm_config_result {
> +       unsigned long status;
> +       unsigned long start;
> +       unsigned long size;
> +       unsigned long settings;
> +};
> +
> +/*
> + * Exchanges capabilities between normal world and secure world
> + *
> + * Call register usage:
> + * a0  SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES
> + * a1  bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_*
> + * a2-6        Not used
> + * a7  Hypervisor Client ID register
> + *
> + * Normal return register usage:
> + * a0  OPTEE_SMC_RETURN_OK
> + * a1  bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
> + * a2-7        Preserved
> + *
> + * Error return register usage:
> + * a0  OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world
> + * a1  bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
> + * a2-7 Preserved
> + */
> +/* Normal world works as a uniprocessor system */
> +#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR                BIT(0)
> +/* Secure world has reserved shared memory for normal world to use */
> +#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM    BIT(0)
> +/* Secure world can communicate via previously unregistered shared memory */
> +#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM     BIT(1)
> +
> +/*
> + * Secure world supports commands "register/unregister shared memory",
> + * secure world accepts command buffers located in any parts of non-secure RAM
> + */
> +#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM          BIT(2)
> +
> +#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
> +#define OPTEE_SMC_EXCHANGE_CAPABILITIES \
> +       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
> +
> +struct optee_smc_exchange_capabilities_result {
> +       unsigned long status;
> +       unsigned long capabilities;
> +       unsigned long reserved0;
> +       unsigned long reserved1;
> +};
> +
> +/*
> + * Disable and empties cache of shared memory objects
> + *
> + * Secure world can cache frequently used shared memory objects, for
> + * example objects used as RPC arguments. When secure world is idle this
> + * function returns one shared memory reference to free. To disable the
> + * cache and free all cached objects this function has to be called until
> + * it returns OPTEE_SMC_RETURN_ENOTAVAIL.
> + *
> + * Call register usage:
> + * a0  SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE
> + * a1-6        Not used
> + * a7  Hypervisor Client ID register
> + *
> + * Normal return register usage:
> + * a0  OPTEE_SMC_RETURN_OK
> + * a1  Upper 32bit of a 64bit Shared memory cookie
> + * a2  Lower 32bit of a 64bit Shared memory cookie
> + * a3-7        Preserved
> + *
> + * Cache empty return register usage:
> + * a0  OPTEE_SMC_RETURN_ENOTAVAIL
> + * a1-7        Preserved
> + *
> + * Not idle return register usage:
> + * a0  OPTEE_SMC_RETURN_EBUSY
> + * a1-7        Preserved
> + */
> +#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE     10
> +#define OPTEE_SMC_DISABLE_SHM_CACHE \
> +       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE)
> +
> +struct optee_smc_disable_shm_cache_result {
> +       unsigned long status;
> +       unsigned long shm_upper32;
> +       unsigned long shm_lower32;
> +       unsigned long reserved0;
> +};
> +
> +/*
> + * Enable cache of shared memory objects
> + *
> + * Secure world can cache frequently used shared memory objects, for
> + * example objects used as RPC arguments. When secure world is idle this
> + * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If
> + * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned.
> + *
> + * Call register usage:
> + * a0  SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE
> + * a1-6        Not used
> + * a7  Hypervisor Client ID register
> + *
> + * Normal return register usage:
> + * a0  OPTEE_SMC_RETURN_OK
> + * a1-7        Preserved
> + *
> + * Not idle return register usage:
> + * a0  OPTEE_SMC_RETURN_EBUSY
> + * a1-7        Preserved
> + */
> +#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE      11
> +#define OPTEE_SMC_ENABLE_SHM_CACHE \
> +       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
> +
> +/*
> + * Resume from RPC (for example after processing a foreign interrupt)
> + *
> + * Call register usage:
> + * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
> + * a1-3        Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned
> + *     OPTEE_SMC_RETURN_RPC in a0
> + *
> + * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above.
> + *
> + * Possible return values
> + * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION   Trusted OS does not recognize this
> + *                                     function.
> + * OPTEE_SMC_RETURN_OK                 Original call completed, result
> + *                                     updated in the previously supplied.
> + *                                     struct optee_msg_arg
> + * OPTEE_SMC_RETURN_RPC                        Call suspended by RPC call to normal
> + *                                     world.
> + * OPTEE_SMC_RETURN_ERESUME            Resume failed, the opaque resume
> + *                                     information was corrupt.
> + */
> +#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC       3
> +#define OPTEE_SMC_CALL_RETURN_FROM_RPC \
> +       OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC)
> +
> +#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK       0xFFFF0000
> +#define OPTEE_SMC_RETURN_RPC_PREFIX            0xFFFF0000
> +#define OPTEE_SMC_RETURN_RPC_FUNC_MASK         0x0000FFFF
> +
> +#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \
> +       ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK)
> +
> +#define OPTEE_SMC_RPC_VAL(func)                ((func) | OPTEE_SMC_RETURN_RPC_PREFIX)
> +
> +/*
> + * Allocate memory for RPC parameter passing. The memory is used to hold a
> + * struct optee_msg_arg.
> + *
> + * "Call" register usage:
> + * a0  This value, OPTEE_SMC_RETURN_RPC_ALLOC
> + * a1  Size in bytes of required argument memory
> + * a2  Not used
> + * a3  Resume information, must be preserved
> + * a4-5        Not used
> + * a6-7        Resume information, must be preserved
> + *
> + * "Return" register usage:
> + * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
> + * a1  Upper 32bits of 64bit physical pointer to allocated
> + *     memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
> + *     be allocated.
> + * a2  Lower 32bits of 64bit physical pointer to allocated
> + *     memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
> + *     be allocated
> + * a3  Preserved
> + * a4  Upper 32bits of 64bit Shared memory cookie used when freeing
> + *     the memory or doing an RPC
> + * a5  Lower 32bits of 64bit Shared memory cookie used when freeing
> + *     the memory or doing an RPC
> + * a6-7        Preserved
> + */
> +#define OPTEE_SMC_RPC_FUNC_ALLOC       0
> +#define OPTEE_SMC_RETURN_RPC_ALLOC \
> +       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC)
> +
> +/*
> + * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC
> + *
> + * "Call" register usage:
> + * a0  This value, OPTEE_SMC_RETURN_RPC_FREE
> + * a1  Upper 32bits of 64bit shared memory cookie belonging to this
> + *     argument memory
> + * a2  Lower 32bits of 64bit shared memory cookie belonging to this
> + *     argument memory
> + * a3-7        Resume information, must be preserved
> + *
> + * "Return" register usage:
> + * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
> + * a1-2        Not used
> + * a3-7        Preserved
> + */
> +#define OPTEE_SMC_RPC_FUNC_FREE                2
> +#define OPTEE_SMC_RETURN_RPC_FREE \
> +       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
> +
> +/*
> + * Deliver foreign interrupt to normal world.
> + *
> + * "Call" register usage:
> + * a0  OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
> + * a1-7        Resume information, must be preserved
> + *
> + * "Return" register usage:
> + * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
> + * a1-7        Preserved
> + */
> +#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR                4
> +#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
> +       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
> +
> +/*
> + * Do an RPC request. The supplied struct optee_msg_arg tells which
> + * request to do and the parameters for the request. The following fields
> + * are used (the rest are unused):
> + * - cmd               the Request ID
> + * - ret               return value of the request, filled in by normal world
> + * - num_params                number of parameters for the request
> + * - params            the parameters
> + * - param_attrs       attributes of the parameters
> + *
> + * "Call" register usage:
> + * a0  OPTEE_SMC_RETURN_RPC_CMD
> + * a1  Upper 32bit of a 64bit Shared memory cookie holding a
> + *     struct optee_msg_arg, must be preserved, only the data should
> + *     be updated
> + * a2  Lower 32bit of a 64bit Shared memory cookie holding a
> + *     struct optee_msg_arg, must be preserved, only the data should
> + *     be updated
> + * a3-7        Resume information, must be preserved
> + *
> + * "Return" register usage:
> + * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
> + * a1-2        Not used
> + * a3-7        Preserved
> + */
> +#define OPTEE_SMC_RPC_FUNC_CMD         5
> +#define OPTEE_SMC_RETURN_RPC_CMD \
> +       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
> +
> +/* Returned in a0 */
> +#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
> +
> +/* Returned in a0 only from Trusted OS functions */
> +#define OPTEE_SMC_RETURN_OK            0x0
> +#define OPTEE_SMC_RETURN_ETHREAD_LIMIT 0x1
> +#define OPTEE_SMC_RETURN_EBUSY         0x2
> +#define OPTEE_SMC_RETURN_ERESUME       0x3
> +#define OPTEE_SMC_RETURN_EBADADDR      0x4
> +#define OPTEE_SMC_RETURN_EBADCMD       0x5
> +#define OPTEE_SMC_RETURN_ENOMEM                0x6
> +#define OPTEE_SMC_RETURN_ENOTAVAIL     0x7
> +#define OPTEE_SMC_RETURN_IS_RPC(ret)   __optee_smc_return_is_rpc((ret))
> +
> +static inline bool __optee_smc_return_is_rpc(u32 ret)
> +{
> +       return ret != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION &&
> +              (ret & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==
> +                       OPTEE_SMC_RETURN_RPC_PREFIX;
> +}
> +
> +#endif /* OPTEE_SMC_H */
> diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c
> new file mode 100644
> index 000000000000..6965055bd1b5
> --- /dev/null
> +++ b/drivers/tee/optee/supplicant.c
> @@ -0,0 +1,89 @@
> +// SPDX-License-Identifier: BSD-2-Clause
> +/*
> + * Copyright (c) 2018, Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <linux/types.h>
> +#include <log.h>
> +#include <tee.h>
> +
> +#include "optee_msg.h"
> +#include "optee_msg_supplicant.h"
> +#include "optee_private.h"
> +#include "optee_smc.h"
> +
> +static void cmd_shm_alloc(struct udevice *dev, struct optee_msg_arg *arg,
> +                         void **page_list)
> +{
> +       struct tee_shm *shm;
> +       void *pl;
> +       u64 ph_ptr;
> +
> +       arg->ret_origin = TEE_ORIGIN_COMMS;
> +
> +       if (arg->num_params != 1 ||
> +           arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
> +               arg->ret = TEE_ERROR_BAD_PARAMETERS;
> +               return;
> +       }
> +
> +       shm = __tee_shm_add(dev, 0, NULL, arg->params[0].u.value.b,
> +                           TEE_SHM_REGISTER | TEE_SHM_ALLOC);
> +       if (!shm) {
> +               arg->ret = TEE_ERROR_OUT_OF_MEMORY;
> +               return;
> +       }
> +
> +       pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr);
> +       if (!pl) {
> +               arg->ret = TEE_ERROR_OUT_OF_MEMORY;
> +               tee_shm_free(shm);
> +               return;
> +       }
> +
> +       *page_list = pl;
> +       arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
> +                             OPTEE_MSG_ATTR_NONCONTIG;
> +       arg->params[0].u.tmem.buf_ptr = ph_ptr;
> +       arg->params[0].u.tmem.size = shm->size;
> +       arg->params[0].u.tmem.shm_ref = (ulong)shm;
> +       arg->ret = TEE_SUCCESS;
> +}
> +
> +static void cmd_shm_free(struct optee_msg_arg *arg)
> +{
> +       arg->ret_origin = TEE_ORIGIN_COMMS;
> +
> +       if (arg->num_params != 1 ||
> +           arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
> +               arg->ret = TEE_ERROR_BAD_PARAMETERS;
> +               return;
> +       }
> +
> +       tee_shm_free((struct tee_shm *)(ulong)arg->params[0].u.value.b);
> +       arg->ret = TEE_SUCCESS;
> +}
> +
> +void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
> +                    void **page_list)
> +{
> +       struct optee_msg_arg *arg = shm_arg->addr;
> +
> +       switch (arg->cmd) {
> +       case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
> +               cmd_shm_alloc(dev, arg, page_list);
> +               break;
> +       case OPTEE_MSG_RPC_CMD_SHM_FREE:
> +               cmd_shm_free(arg);
> +               break;
> +       case OPTEE_MSG_RPC_CMD_FS:
> +               debug("OPTEE_MSG_RPC_CMD_FS not implemented\n");
> +               arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
> +               break;
> +       default:
> +               arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
> +       }
> +
> +       arg->ret_origin = TEE_ORIGIN_COMMS;
> +}
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application
  2018-08-13 15:53 ` [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application Jens Wiklander
@ 2018-08-16 12:22   ` Igor Opaniuk
  2018-08-19 12:42     ` Igor Opaniuk
  0 siblings, 1 reply; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-16 12:22 UTC (permalink / raw)
  To: u-boot

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds configuration option OPTEE_TA_AVB and a header file describing the
> interface to the AVB trusted application provided by OP-TEE.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  MAINTAINERS                |  1 +
>  drivers/tee/optee/Kconfig  | 16 +++++++++++++
>  include/tee.h              |  7 ++++++
>  include/tee/optee_ta_avb.h | 48 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 72 insertions(+)
>  create mode 100644 include/tee/optee_ta_avb.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7458c606ee92..cb36c45d74ea 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -576,6 +576,7 @@ M:  Jens Wiklander <jens.wiklander@linaro.org>
>  S:     Maintained
>  F:     drivers/tee/
>  F:     include/tee.h
> +F:     include/tee/
>
>  UBI
>  M:     Kyungmin Park <kmpark@infradead.org>
> diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
> index 8f7ebe161111..a5dc08439629 100644
> --- a/drivers/tee/optee/Kconfig
> +++ b/drivers/tee/optee/Kconfig
> @@ -5,3 +5,19 @@ config OPTEE
>         help
>           This implements the OP-TEE Trusted Execution Environment (TEE)
>           driver.
> +
> +if OPTEE
> +
> +menu "OP-TEE options"
> +
> +config OPTEE_TA_AVB
> +       bool "Support AVB TA"
> +       default y
> +       help
> +         Enables support for the AVB Trusted Application (TA) in OP-TEE.
> +         The TA can support the "avb" subcommands "read_rb", "write"rb"
> +         and "is_unlocked".
> +
> +endmenu
> +
> +endif
> diff --git a/include/tee.h b/include/tee.h
> index c2ac13e34128..3d95d4b3f740 100644
> --- a/include/tee.h
> +++ b/include/tee.h
> @@ -48,6 +48,13 @@
>
>  struct tee_driver_ops;
>
> +struct tee_optee_ta_uuid {
> +       u32 time_low;
> +       u16 time_mid;
> +       u16 time_hi_and_version;
> +       u8 clock_seq_and_node[8];
> +};
> +
>  struct tee_shm {
>         struct udevice *dev;
>         struct list_head link;
> diff --git a/include/tee/optee_ta_avb.h b/include/tee/optee_ta_avb.h
> new file mode 100644
> index 000000000000..0e1da084e09d
> --- /dev/null
> +++ b/include/tee/optee_ta_avb.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +/* Copyright (c) 2018, Linaro Limited */
> +
> +#ifndef __TA_AVB_H
> +#define __TA_AVB_H
> +
> +#define TA_AVB_UUID { 0x023f8f1a, 0x292a, 0x432b, \
> +                     { 0x8f, 0xc4, 0xde, 0x84, 0x71, 0x35, 0x80, 0x67 } }
> +
> +#define TA_AVB_MAX_ROLLBACK_LOCATIONS  256
> +
> +/*
> + * Gets the rollback index corresponding to the given rollback index slot.
> + *
> + * in  params[0].value.a:      rollback index slot
> + * out params[1].value.a:      upper 32 bits of rollback index
> + * out params[1].value.b:      lower 32 bits of rollback index
> + */
> +#define TA_AVB_CMD_READ_ROLLBACK_INDEX 0
> +
> +/*
> + * Updates the rollback index corresponding to the given rollback index slot.
> + *
> + * Will refuse to update a slot with a lower value.
> + *
> + * in  params[0].value.a:      rollback index slot
> + * in  params[1].value.a:      upper 32 bits of rollback index
> + * in  params[1].value.b:      lower 32 bits of rollback index
> + */
> +#define TA_AVB_CMD_WRITE_ROLLBACK_INDEX        1
> +
> +/*
> + * Gets the lock state of the device.
> + *
> + * out params[0].value.a:      lock state
> + */
> +#define TA_AVB_CMD_READ_LOCK_STATE     2
> +
> +/*
> + * Sets the lock state of the device.
> + *
> + * If the lock state is changed all rollback slots will be reset to 0
> + *
> + * in  params[0].value.a:      lock state
> + */
> +#define TA_AVB_CMD_WRITE_LOCK_STATE    3
> +
> +#endif /*__TA_AVB_H*/
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 08/10] optee: support routing of rpmb data frames to mmc
  2018-08-13 15:53 ` [U-Boot] [PATCH 08/10] optee: support routing of rpmb data frames to mmc Jens Wiklander
@ 2018-08-16 12:23   ` Igor Opaniuk
  0 siblings, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-16 12:23 UTC (permalink / raw)
  To: u-boot

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds support in optee supplicant to route signed (MACed) RPMB frames
> from OP-TEE Secure OS to MMC and vice versa to manipulate the RPMB
> partition.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  drivers/tee/optee/Makefile        |   1 +
>  drivers/tee/optee/core.c          |   8 ++
>  drivers/tee/optee/optee_private.h |  31 ++++-
>  drivers/tee/optee/rpmb.c          | 184 ++++++++++++++++++++++++++++++
>  drivers/tee/optee/supplicant.c    |   3 +
>  5 files changed, 226 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/tee/optee/rpmb.c
>
> diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
> index 6148feb474a5..928d3f80027f 100644
> --- a/drivers/tee/optee/Makefile
> +++ b/drivers/tee/optee/Makefile
> @@ -2,3 +2,4 @@
>
>  obj-y += core.o
>  obj-y += supplicant.o
> +obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> index a810f3b965de..5f308a0c6a96 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -280,6 +280,13 @@ static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg)
>                         param.a3 = res.a3;
>                         handle_rpc(dev, &param, &page_list);
>                 } else {
> +                       /*
> +                        * In case we've accessed RPMB to serve an RPC
> +                        * request we need to restore the previously
> +                        * selected partition as the caller may expect it
> +                        * to remain unchanged.
> +                        */
> +                       optee_suppl_rpmb_release(dev);
>                         return call_err_to_res(res.a0);
>                 }
>         }
> @@ -611,4 +618,5 @@ U_BOOT_DRIVER(optee) = {
>         .probe = optee_probe,
>         .ops = &optee_ops,
>         .platdata_auto_alloc_size = sizeof(struct optee_pdata),
> +       .priv_auto_alloc_size = sizeof(struct optee_private),
>  };
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index daa470f812a9..b76979d21011 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -6,7 +6,36 @@
>  #ifndef __OPTEE_PRIVATE_H
>  #define __OPTEE_PRIVATE_H
>
> +#include <tee.h>
> +#include <log.h>
> +
> +struct optee_private {
> +       struct mmc *rpmb_mmc;
> +       int rpmb_dev_id;
> +       char rpmb_original_part;
> +};
> +
> +struct optee_msg_arg;
> +
> +void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
> +                    void **page_list);
> +
> +#ifdef CONFIG_SUPPORT_EMMC_RPMB
> +void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg);
> +void optee_suppl_rpmb_release(struct udevice *dev);
> +#else
> +static inline void optee_suppl_cmd_rpmb(struct udevice *dev,
> +                                       struct optee_msg_arg *arg)
> +{
> +       debug("OPTEE_MSG_RPC_CMD_RPMB not implemented\n");
> +       arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
> +}
> +
> +static inline void optee_suppl_rpmb_release(struct udevice *dev)
> +{
> +}
> +#endif
> +
>  void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr);
> -void optee_suppl_cmd(struct udevice *dev, void *shm, void **page_list);
>
>  #endif /*__OPTEE_PRIVATE_H*/
> diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
> new file mode 100644
> index 000000000000..c1447a5561c2
> --- /dev/null
> +++ b/drivers/tee/optee/rpmb.c
> @@ -0,0 +1,184 @@
> +// SPDX-License-Identifier: BSD-2-Clause
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <log.h>
> +#include <tee.h>
> +#include <mmc.h>
> +
> +#include "optee_msg.h"
> +#include "optee_private.h"
> +
> +/*
> + * Request and response definitions must be in sync with the secure side of
> + * OP-TEE.
> + */
> +
> +/* Request */
> +struct rpmb_req {
> +       u16 cmd;
> +#define RPMB_CMD_DATA_REQ      0x00
> +#define RPMB_CMD_GET_DEV_INFO  0x01
> +       u16 dev_id;
> +       u16 block_count;
> +       /* Optional data frames (rpmb_data_frame) follow */
> +};
> +
> +#define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))
> +
> +/* Response to device info request */
> +struct rpmb_dev_info {
> +       u8 cid[16];
> +       u8 rpmb_size_mult;      /* EXT CSD-slice 168: RPMB Size */
> +       u8 rel_wr_sec_c;        /* EXT CSD-slice 222: Reliable Write Sector */
> +                               /*                    Count */
> +       u8 ret_code;
> +#define RPMB_CMD_GET_DEV_INFO_RET_OK     0x00
> +#define RPMB_CMD_GET_DEV_INFO_RET_ERROR  0x01
> +};
> +
> +static void release_mmc(struct optee_private *priv)
> +{
> +       int rc;
> +
> +       if (!priv->rpmb_mmc)
> +               return;
> +
> +       rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
> +                                     priv->rpmb_original_part);
> +       if (rc)
> +               debug("%s: blk_select_hwpart_devnum() failed: %d\n",
> +                     __func__, rc);
> +
> +       priv->rpmb_mmc = NULL;
> +}
> +
> +static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
> +{
> +       struct mmc *mmc;
> +       int rc;
> +
> +       if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
> +               return priv->rpmb_mmc;
> +
> +       release_mmc(priv);
> +
> +       mmc = find_mmc_device(dev_id);
> +       if (!mmc) {
> +               debug("Cannot find RPMB device\n");
> +               return NULL;
> +       }
> +       if (!(mmc->version & MMC_VERSION_MMC)) {
> +               debug("Device id %d is not an eMMC device\n", dev_id);
> +               return NULL;
> +       }
> +       if (mmc->version < MMC_VERSION_4_41) {
> +               debug("Device id %d: RPMB not supported before version 4.41\n",
> +                     dev_id);
> +               return NULL;
> +       }
> +
> +#ifdef CONFIG_BLK
> +       priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
> +#else
> +       priv->rpmb_original_part = mmc->block_dev.hwpart;
> +#endif
> +
> +       rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
> +       if (rc) {
> +               debug("Device id %d: cannot select RPMB partition: %d\n",
> +                     dev_id, rc);
> +               return NULL;
> +       }
> +
> +       priv->rpmb_mmc = mmc;
> +       priv->rpmb_dev_id = dev_id;
> +       return mmc;
> +}
> +
> +static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
> +{
> +       struct mmc *mmc = find_mmc_device(dev_id);
> +
> +       if (!mmc)
> +               return TEE_ERROR_ITEM_NOT_FOUND;
> +
> +       if (!mmc->ext_csd)
> +               return TEE_ERROR_GENERIC;
> +
> +       memcpy(info->cid, mmc->cid, sizeof(info->cid));
> +       info->rel_wr_sec_c = mmc->ext_csd[222];
> +       info->rpmb_size_mult = mmc->ext_csd[168];
> +       info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;
> +
> +       return TEE_SUCCESS;
> +}
> +
> +static u32 rpmb_process_request(struct optee_private *priv, void *req,
> +                               ulong req_size, void *rsp, ulong rsp_size)
> +{
> +       struct rpmb_req *sreq = req;
> +       struct mmc *mmc;
> +
> +       if (req_size < sizeof(*sreq))
> +               return TEE_ERROR_BAD_PARAMETERS;
> +
> +       switch (sreq->cmd) {
> +       case RPMB_CMD_DATA_REQ:
> +               mmc = get_mmc(priv, sreq->dev_id);
> +               if (!mmc)
> +                       return TEE_ERROR_ITEM_NOT_FOUND;
> +               if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
> +                                         req_size - sizeof(struct rpmb_req),
> +                                         rsp, rsp_size))
> +                       return TEE_ERROR_BAD_PARAMETERS;
> +               return TEE_SUCCESS;
> +
> +       case RPMB_CMD_GET_DEV_INFO:
> +               if (req_size != sizeof(struct rpmb_req) ||
> +                   rsp_size != sizeof(struct rpmb_dev_info)) {
> +                       debug("Invalid req/rsp size\n");
> +                       return TEE_ERROR_BAD_PARAMETERS;
> +               }
> +               return rpmb_get_dev_info(sreq->dev_id, rsp);
> +
> +       default:
> +               debug("Unsupported RPMB command: %d\n", sreq->cmd);
> +               return TEE_ERROR_BAD_PARAMETERS;
> +       }
> +}
> +
> +void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
> +{
> +       struct tee_shm *req_shm;
> +       struct tee_shm *rsp_shm;
> +       void *req_buf;
> +       void *rsp_buf;
> +       ulong req_size;
> +       ulong rsp_size;
> +
> +       if (arg->num_params != 2 ||
> +           arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
> +           arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
> +               arg->ret = TEE_ERROR_BAD_PARAMETERS;
> +               return;
> +       }
> +
> +       req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
> +       req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
> +       req_size = arg->params[0].u.rmem.size;
> +
> +       rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
> +       rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
> +       rsp_size = arg->params[1].u.rmem.size;
> +
> +       arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
> +                                       rsp_buf, rsp_size);
> +}
> +
> +void optee_suppl_rpmb_release(struct udevice *dev)
> +{
> +       release_mmc(dev_get_priv(dev));
> +}
> diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c
> index 6965055bd1b5..14cb8717522c 100644
> --- a/drivers/tee/optee/supplicant.c
> +++ b/drivers/tee/optee/supplicant.c
> @@ -81,6 +81,9 @@ void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
>                 debug("OPTEE_MSG_RPC_CMD_FS not implemented\n");
>                 arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
>                 break;
> +       case OPTEE_MSG_RPC_CMD_RPMB:
> +               optee_suppl_cmd_rpmb(dev, arg);
> +               break;
>         default:
>                 arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
>         }
> --
> 2.17.1
>



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-13 15:53 ` [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
  2018-08-16 12:14   ` Igor Opaniuk
@ 2018-08-17 12:48   ` Simon Glass
  2018-08-21  9:20     ` Jens Wiklander
  2018-08-23 10:45   ` Simon Glass
  2 siblings, 1 reply; 40+ messages in thread
From: Simon Glass @ 2018-08-17 12:48 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds a uclass to interface with a TEE (Trusted Execution Environment).
>
> A TEE driver is a driver that interfaces with a trusted OS running in
> some secure environment, for example, TrustZone on ARM cpus, or a
> separate secure co-processor etc.
>
> The TEE subsystem can serve a TEE driver for a Global Platform compliant
> TEE, but it's not limited to only Global Platform TEEs.
>
> The over all design is based on the TEE subsystem in the Linux kernel,
> tailored for U-boot.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  MAINTAINERS              |   6 ++
>  drivers/Kconfig          |   2 +
>  drivers/Makefile         |   1 +
>  drivers/tee/Kconfig      |   8 ++
>  drivers/tee/Makefile     |   3 +
>  drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h   |   1 +
>  include/tee.h            | 134 +++++++++++++++++++++++++++++
>  8 files changed, 335 insertions(+)
>  create mode 100644 drivers/tee/Kconfig
>  create mode 100644 drivers/tee/Makefile
>  create mode 100644 drivers/tee/tee-uclass.c
>  create mode 100644 include/tee.h
>

Please add a sandbox driver and a test in test/dm for any new uclass.

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 58b61ac05882..7458c606ee92 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -571,6 +571,12 @@ TQ GROUP
>  S:     Orphaned (Since 2016-02)
>  T:     git git://git.denx.de/u-boot-tq-group.git
>
> +TEE
> +M:     Jens Wiklander <jens.wiklander@linaro.org>
> +S:     Maintained
> +F:     drivers/tee/
> +F:     include/tee.h
> +
>  UBI
>  M:     Kyungmin Park <kmpark@infradead.org>
>  M:     Heiko Schocher <hs@denx.de>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c72abf893297..f3249ab1d143 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
>
>  source "drivers/sysreset/Kconfig"
>
> +source "drivers/tee/Kconfig"
> +
>  source "drivers/thermal/Kconfig"
>
>  source "drivers/timer/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index d53208540ea6..0fcae36f50f7 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -103,6 +103,7 @@ obj-y += smem/
>  obj-y += soc/
>  obj-$(CONFIG_REMOTEPROC) += remoteproc/
>  obj-y += thermal/
> +obj-$(CONFIG_TEE) += tee/
>
>  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
>  endif
> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
> new file mode 100644
> index 000000000000..817ab331b0f8
> --- /dev/null
> +++ b/drivers/tee/Kconfig
> @@ -0,0 +1,8 @@
> +# Generic Trusted Execution Environment Configuration
> +config TEE
> +       bool "Trusted Execution Environment support"
> +       depends on ARM && (ARM64 || CPU_V7A)
> +       select ARM_SMCCC
> +       help
> +         This implements a generic interface towards a Trusted Execution
> +         Environment (TEE).
> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> new file mode 100644
> index 000000000000..b6d8e16e6211
> --- /dev/null
> +++ b/drivers/tee/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += tee-uclass.o
> diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
> new file mode 100644
> index 000000000000..f0243a0f2e4e
> --- /dev/null
> +++ b/drivers/tee/tee-uclass.c
> @@ -0,0 +1,180 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <tee.h>
> +
> +struct tee_uclass_priv {
> +       struct list_head list_shm;

Struct comment please

> +};
> +
> +static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
> +{
> +       return device_get_ops(dev);
> +}
> +
> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
> +{
> +       tee_get_ops(dev)->get_version(dev, vers);
> +}
> +
> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> +                    ulong num_param, struct tee_param *param)
> +{
> +       return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
> +}
> +
> +int tee_close_session(struct udevice *dev, u32 session)
> +{
> +       return tee_get_ops(dev)->close_session(dev, session);
> +}
> +
> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                   ulong num_param, struct tee_param *param)
> +{
> +       return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
> +}
> +
> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> +                             ulong size, u32 flags)
> +{
> +       struct tee_shm *shm;
> +       void *p = addr;
> +
> +       if (flags & TEE_SHM_ALLOC) {
> +               if (align)
> +                       p = memalign(align, size);
> +               else
> +                       p = malloc(size);
> +       }
> +       if (!p)
> +               return NULL;
> +
> +       shm = calloc(1, sizeof(*shm));

Rather than allocating memory here, can you use driver-model's
auto-alloc features?

> +       if (!shm)
> +               goto err;
> +
> +       shm->dev = dev;
> +       shm->addr = p;
> +       shm->size = size;
> +       shm->flags = flags;
> +
> +       if ((flags & TEE_SHM_SEC_REGISTER) &&
> +           tee_get_ops(dev)->shm_register(dev, shm))
> +               goto err;
> +
> +       if (flags & TEE_SHM_REGISTER) {
> +               struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +
> +               list_add(&shm->link, &priv->list_shm);
> +       }
> +       return shm;
> +err:
> +       free(shm);
> +       if (flags & TEE_SHM_ALLOC)
> +               free(p);
> +       return NULL;
> +}
> +
> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
> +                             u32 flags)
> +{
> +       u32 f = flags;
> +
> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
> +       return __tee_shm_add(dev, 0, NULL, size, f);
> +}
> +
> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> +                                ulong size, u32 flags)
> +{
> +       u32 f = flags & ~TEE_SHM_ALLOC;
> +
> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
> +       return __tee_shm_add(dev, 0, addr, size, f);
> +}
> +
> +void tee_shm_free(struct tee_shm *shm)
> +{
> +       if (!shm)
> +               return;
> +
> +       if (shm->flags & TEE_SHM_SEC_REGISTER)
> +               tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
> +
> +       if (shm->flags & TEE_SHM_REGISTER)
> +               list_del(&shm->link);
> +
> +       if (shm->flags & TEE_SHM_ALLOC)
> +               free(shm->addr);
> +
> +       free(shm);
> +}
> +
> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +       struct tee_shm *s;
> +
> +       list_for_each_entry(s, &priv->list_shm, link)
> +               if (s == shm)
> +                       return true;
> +
> +       return false;
> +}
> +
> +struct udevice *tee_find_device(struct udevice *start,
> +                               int (*match)(struct tee_version_data *vers,
> +                                            const void *data),
> +                               const void *data,
> +                               struct tee_version_data *vers)

'find' should find the device, not probe anything. Is that what this does?

> +{
> +       struct udevice *dev = start;
> +       struct tee_version_data lv;
> +       struct tee_version_data *v = vers ? vers : &lv;
> +
> +       if (!dev)
> +               uclass_first_device(UCLASS_TEE, &dev);
> +
> +       for (; dev; uclass_next_device(&dev)) {
> +               tee_get_ops(dev)->get_version(dev, v);
> +               if (!match || match(v, data))
> +                       return dev;
> +       }
> +
> +       return NULL;
> +}
> +
> +static int tee_pre_probe(struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +
> +       INIT_LIST_HEAD(&priv->list_shm);

blank line before return

> +       return 0;
> +}
> +
> +static int tee_pre_remove(struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +       struct tee_shm *shm;
> +
> +       while (!list_empty(&priv->list_shm)) {
> +               shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
> +               debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
> +                     __func__, (void *)shm, shm->size, shm->flags);
> +               tee_shm_free(shm);
> +       }
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(tee) = {
> +       .id = UCLASS_TEE,
> +       .name = "tee",
> +       .per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
> +       .pre_probe = tee_pre_probe,
> +       .pre_remove = tee_pre_remove,
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a39643ec5eef..955e0a915b87 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -81,6 +81,7 @@ enum uclass_id {
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
>         UCLASS_SYSRESET,        /* System reset device */
> +       UCLASS_TEE,             /* Trusted Execution Environment device */
>         UCLASS_THERMAL,         /* Thermal sensor */
>         UCLASS_TIMER,           /* Timer device */
>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
> diff --git a/include/tee.h b/include/tee.h
> new file mode 100644
> index 000000000000..c2ac13e34128
> --- /dev/null
> +++ b/include/tee.h
> @@ -0,0 +1,134 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#ifndef __TEE_H
> +#define __TEE_H
> +
> +#include <common.h>
> +#include <dm.h>
> +
> +#define TEE_UUID_LEN           16
> +
> +#define TEE_GEN_CAP_GP          BIT(0) /* GlobalPlatform compliant TEE */
> +#define TEE_GEN_CAP_REG_MEM     BIT(1) /* Supports registering shared memory */
> +
> +#define TEE_SHM_REGISTER       BIT(0)
> +#define TEE_SHM_SEC_REGISTER   BIT(1)
> +#define TEE_SHM_ALLOC          BIT(2)
> +
> +#define TEE_PARAM_ATTR_TYPE_NONE               0       /* parameter not used */
> +#define TEE_PARAM_ATTR_TYPE_VALUE_INPUT                1
> +#define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT       2
> +#define TEE_PARAM_ATTR_TYPE_VALUE_INOUT                3       /* input and output */
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT       5
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT      6
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT       7       /* input and output */
> +#define TEE_PARAM_ATTR_TYPE_MASK               0xff
> +#define TEE_PARAM_ATTR_META                    0x100
> +#define TEE_PARAM_ATTR_MASK                    (TEE_PARAM_ATTR_TYPE_MASK | \
> +                                                TEE_PARAM_ATTR_META)
> +
> +/*
> + * Some Global Platform error codes which has a meaning if the
> + * TEE_GEN_CAP_GP bit is returned by the driver.
> + */
> +#define TEE_SUCCESS                    0x00000000
> +#define TEE_ERROR_GENERIC              0xffff0000
> +#define TEE_ERROR_BAD_PARAMETERS       0xffff0006
> +#define TEE_ERROR_ITEM_NOT_FOUND       0xffff0008
> +#define TEE_ERROR_NOT_IMPLEMENTED      0xffff0009
> +#define TEE_ERROR_NOT_SUPPORTED                0xffff000a
> +#define TEE_ERROR_COMMUNICATION                0xffff000e
> +#define TEE_ERROR_OUT_OF_MEMORY                0xffff000c
> +#define TEE_ERROR_TARGET_DEAD          0xffff3024
> +
> +#define TEE_ORIGIN_COMMS               0x00000002
> +
> +struct tee_driver_ops;
> +
> +struct tee_shm {

comments for these structs please.

Also the whole uclass needs a README or more docs. Perhaps I have missed this?

> +       struct udevice *dev;
> +       struct list_head link;
> +       void *addr;
> +       ulong size;
> +       u32 flags;
> +};
> +
> +struct tee_param_memref {
> +       ulong shm_offs;
> +       ulong size;
> +       struct tee_shm *shm;
> +};
> +
> +struct tee_param_value {
> +       u64 a;
> +       u64 b;
> +       u64 c;
> +};
> +
> +struct tee_param {
> +       u64 attr;
> +       union {
> +               struct tee_param_memref memref;
> +               struct tee_param_value value;
> +       } u;
> +};
> +
> +struct tee_open_session_arg {
> +       u8 uuid[TEE_UUID_LEN];
> +       u8 clnt_uuid[TEE_UUID_LEN];
> +       u32 clnt_login;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +struct tee_invoke_arg {
> +       u32 func;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +struct tee_version_data {
> +       u32 gen_caps;
> +};
> +
> +struct tee_driver_ops {
> +       void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
> +       int (*open_session)(struct udevice *dev,
> +                           struct tee_open_session_arg *arg, ulong num_param,
> +                           struct tee_param *param);
> +       int (*close_session)(struct udevice *dev, u32 session);
> +       int (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
> +                          ulong num_param, struct tee_param *param);
> +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
> +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);

Each of these needs a full function comment. Without that I cannot
really comment on the API. Same for functions below.

> +};
> +
> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> +                             ulong size, u32 flags);
> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);
> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> +                                ulong length, u32 flags);
> +void tee_shm_free(struct tee_shm *shm);
> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
> +
> +struct udevice *tee_find_device(struct udevice *start,
> +                               int (*match)(struct tee_version_data *vers,
> +                                            const void *data),
> +                               const void *data,
> +                               struct tee_version_data *vers);
> +
> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> +                    ulong num_param, struct tee_param *param);
> +
> +int tee_close_session(struct udevice *dev, u32 session);
> +
> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                   ulong num_param, struct tee_param *param);
> +
> +#endif /*__TEE_H*/
> --
> 2.17.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application
  2018-08-16 12:22   ` Igor Opaniuk
@ 2018-08-19 12:42     ` Igor Opaniuk
  0 siblings, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-19 12:42 UTC (permalink / raw)
  To: u-boot

Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>

On 16 August 2018 at 15:22, Igor Opaniuk <igor.opaniuk@linaro.org> wrote:
> Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
>
> On 13 August 2018 at 18:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> Adds configuration option OPTEE_TA_AVB and a header file describing the
>> interface to the AVB trusted application provided by OP-TEE.
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  MAINTAINERS                |  1 +
>>  drivers/tee/optee/Kconfig  | 16 +++++++++++++
>>  include/tee.h              |  7 ++++++
>>  include/tee/optee_ta_avb.h | 48 ++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 72 insertions(+)
>>  create mode 100644 include/tee/optee_ta_avb.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 7458c606ee92..cb36c45d74ea 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -576,6 +576,7 @@ M:  Jens Wiklander <jens.wiklander@linaro.org>
>>  S:     Maintained
>>  F:     drivers/tee/
>>  F:     include/tee.h
>> +F:     include/tee/
>>
>>  UBI
>>  M:     Kyungmin Park <kmpark@infradead.org>
>> diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
>> index 8f7ebe161111..a5dc08439629 100644
>> --- a/drivers/tee/optee/Kconfig
>> +++ b/drivers/tee/optee/Kconfig
>> @@ -5,3 +5,19 @@ config OPTEE
>>         help
>>           This implements the OP-TEE Trusted Execution Environment (TEE)
>>           driver.
>> +
>> +if OPTEE
>> +
>> +menu "OP-TEE options"
>> +
>> +config OPTEE_TA_AVB
>> +       bool "Support AVB TA"
>> +       default y
>> +       help
>> +         Enables support for the AVB Trusted Application (TA) in OP-TEE.
>> +         The TA can support the "avb" subcommands "read_rb", "write"rb"
>> +         and "is_unlocked".
>> +
>> +endmenu
>> +
>> +endif
>> diff --git a/include/tee.h b/include/tee.h
>> index c2ac13e34128..3d95d4b3f740 100644
>> --- a/include/tee.h
>> +++ b/include/tee.h
>> @@ -48,6 +48,13 @@
>>
>>  struct tee_driver_ops;
>>
>> +struct tee_optee_ta_uuid {
>> +       u32 time_low;
>> +       u16 time_mid;
>> +       u16 time_hi_and_version;
>> +       u8 clock_seq_and_node[8];
>> +};
>> +
>>  struct tee_shm {
>>         struct udevice *dev;
>>         struct list_head link;
>> diff --git a/include/tee/optee_ta_avb.h b/include/tee/optee_ta_avb.h
>> new file mode 100644
>> index 000000000000..0e1da084e09d
>> --- /dev/null
>> +++ b/include/tee/optee_ta_avb.h
>> @@ -0,0 +1,48 @@
>> +/* SPDX-License-Identifier: BSD-2-Clause */
>> +/* Copyright (c) 2018, Linaro Limited */
>> +
>> +#ifndef __TA_AVB_H
>> +#define __TA_AVB_H
>> +
>> +#define TA_AVB_UUID { 0x023f8f1a, 0x292a, 0x432b, \
>> +                     { 0x8f, 0xc4, 0xde, 0x84, 0x71, 0x35, 0x80, 0x67 } }
>> +
>> +#define TA_AVB_MAX_ROLLBACK_LOCATIONS  256
>> +
>> +/*
>> + * Gets the rollback index corresponding to the given rollback index slot.
>> + *
>> + * in  params[0].value.a:      rollback index slot
>> + * out params[1].value.a:      upper 32 bits of rollback index
>> + * out params[1].value.b:      lower 32 bits of rollback index
>> + */
>> +#define TA_AVB_CMD_READ_ROLLBACK_INDEX 0
>> +
>> +/*
>> + * Updates the rollback index corresponding to the given rollback index slot.
>> + *
>> + * Will refuse to update a slot with a lower value.
>> + *
>> + * in  params[0].value.a:      rollback index slot
>> + * in  params[1].value.a:      upper 32 bits of rollback index
>> + * in  params[1].value.b:      lower 32 bits of rollback index
>> + */
>> +#define TA_AVB_CMD_WRITE_ROLLBACK_INDEX        1
>> +
>> +/*
>> + * Gets the lock state of the device.
>> + *
>> + * out params[0].value.a:      lock state
>> + */
>> +#define TA_AVB_CMD_READ_LOCK_STATE     2
>> +
>> +/*
>> + * Sets the lock state of the device.
>> + *
>> + * If the lock state is changed all rollback slots will be reset to 0
>> + *
>> + * in  params[0].value.a:      lock state
>> + */
>> +#define TA_AVB_CMD_WRITE_LOCK_STATE    3
>> +
>> +#endif /*__TA_AVB_H*/
>> --
>> 2.17.1
>>
>
>
>
> --
> Regards,
> Igor Opaniuk



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-17 12:48   ` Simon Glass
@ 2018-08-21  9:20     ` Jens Wiklander
  0 siblings, 0 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-21  9:20 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, Aug 17, 2018 at 06:48:47AM -0600, Simon Glass wrote:
> Hi Jens,
> 
> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> > Adds a uclass to interface with a TEE (Trusted Execution Environment).
> >
> > A TEE driver is a driver that interfaces with a trusted OS running in
> > some secure environment, for example, TrustZone on ARM cpus, or a
> > separate secure co-processor etc.
> >
> > The TEE subsystem can serve a TEE driver for a Global Platform compliant
> > TEE, but it's not limited to only Global Platform TEEs.
> >
> > The over all design is based on the TEE subsystem in the Linux kernel,
> > tailored for U-boot.
> >
> > Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  MAINTAINERS              |   6 ++
> >  drivers/Kconfig          |   2 +
> >  drivers/Makefile         |   1 +
> >  drivers/tee/Kconfig      |   8 ++
> >  drivers/tee/Makefile     |   3 +
> >  drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
> >  include/dm/uclass-id.h   |   1 +
> >  include/tee.h            | 134 +++++++++++++++++++++++++++++
> >  8 files changed, 335 insertions(+)
> >  create mode 100644 drivers/tee/Kconfig
> >  create mode 100644 drivers/tee/Makefile
> >  create mode 100644 drivers/tee/tee-uclass.c
> >  create mode 100644 include/tee.h
> >
> 
> Please add a sandbox driver and a test in test/dm for any new uclass.

OK

> 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 58b61ac05882..7458c606ee92 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -571,6 +571,12 @@ TQ GROUP
> >  S:     Orphaned (Since 2016-02)
> >  T:     git git://git.denx.de/u-boot-tq-group.git
> >
> > +TEE
> > +M:     Jens Wiklander <jens.wiklander@linaro.org>
> > +S:     Maintained
> > +F:     drivers/tee/
> > +F:     include/tee.h
> > +
> >  UBI
> >  M:     Kyungmin Park <kmpark@infradead.org>
> >  M:     Heiko Schocher <hs@denx.de>
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index c72abf893297..f3249ab1d143 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
> >
> >  source "drivers/sysreset/Kconfig"
> >
> > +source "drivers/tee/Kconfig"
> > +
> >  source "drivers/thermal/Kconfig"
> >
> >  source "drivers/timer/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index d53208540ea6..0fcae36f50f7 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -103,6 +103,7 @@ obj-y += smem/
> >  obj-y += soc/
> >  obj-$(CONFIG_REMOTEPROC) += remoteproc/
> >  obj-y += thermal/
> > +obj-$(CONFIG_TEE) += tee/
> >
> >  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
> >  endif
> > diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
> > new file mode 100644
> > index 000000000000..817ab331b0f8
> > --- /dev/null
> > +++ b/drivers/tee/Kconfig
> > @@ -0,0 +1,8 @@
> > +# Generic Trusted Execution Environment Configuration
> > +config TEE
> > +       bool "Trusted Execution Environment support"
> > +       depends on ARM && (ARM64 || CPU_V7A)
> > +       select ARM_SMCCC
> > +       help
> > +         This implements a generic interface towards a Trusted Execution
> > +         Environment (TEE).
> > diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> > new file mode 100644
> > index 000000000000..b6d8e16e6211
> > --- /dev/null
> > +++ b/drivers/tee/Makefile
> > @@ -0,0 +1,3 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +
> > +obj-y += tee-uclass.o
> > diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
> > new file mode 100644
> > index 000000000000..f0243a0f2e4e
> > --- /dev/null
> > +++ b/drivers/tee/tee-uclass.c
> > @@ -0,0 +1,180 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2018 Linaro Limited
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <tee.h>
> > +
> > +struct tee_uclass_priv {
> > +       struct list_head list_shm;
> 
> Struct comment please
> 
> > +};
> > +
> > +static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
> > +{
> > +       return device_get_ops(dev);
> > +}
> > +
> > +void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
> > +{
> > +       tee_get_ops(dev)->get_version(dev, vers);
> > +}
> > +
> > +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> > +                    ulong num_param, struct tee_param *param)
> > +{
> > +       return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
> > +}
> > +
> > +int tee_close_session(struct udevice *dev, u32 session)
> > +{
> > +       return tee_get_ops(dev)->close_session(dev, session);
> > +}
> > +
> > +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> > +                   ulong num_param, struct tee_param *param)
> > +{
> > +       return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
> > +}
> > +
> > +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> > +                             ulong size, u32 flags)
> > +{
> > +       struct tee_shm *shm;
> > +       void *p = addr;
> > +
> > +       if (flags & TEE_SHM_ALLOC) {
> > +               if (align)
> > +                       p = memalign(align, size);
> > +               else
> > +                       p = malloc(size);
> > +       }
> > +       if (!p)
> > +               return NULL;
> > +
> > +       shm = calloc(1, sizeof(*shm));
> 
> Rather than allocating memory here, can you use driver-model's
> auto-alloc features?

I don't see how that can be done, these shared memory objects are
dynamically allocated by the client. The number of needed objects isn't
easily predicted.

> 
> > +       if (!shm)
> > +               goto err;
> > +
> > +       shm->dev = dev;
> > +       shm->addr = p;
> > +       shm->size = size;
> > +       shm->flags = flags;
> > +
> > +       if ((flags & TEE_SHM_SEC_REGISTER) &&
> > +           tee_get_ops(dev)->shm_register(dev, shm))
> > +               goto err;
> > +
> > +       if (flags & TEE_SHM_REGISTER) {
> > +               struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> > +
> > +               list_add(&shm->link, &priv->list_shm);
> > +       }
> > +       return shm;
> > +err:
> > +       free(shm);
> > +       if (flags & TEE_SHM_ALLOC)
> > +               free(p);
> > +       return NULL;
> > +}
> > +
> > +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
> > +                             u32 flags)
> > +{
> > +       u32 f = flags;
> > +
> > +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
> > +       return __tee_shm_add(dev, 0, NULL, size, f);
> > +}
> > +
> > +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> > +                                ulong size, u32 flags)
> > +{
> > +       u32 f = flags & ~TEE_SHM_ALLOC;
> > +
> > +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
> > +       return __tee_shm_add(dev, 0, addr, size, f);
> > +}
> > +
> > +void tee_shm_free(struct tee_shm *shm)
> > +{
> > +       if (!shm)
> > +               return;
> > +
> > +       if (shm->flags & TEE_SHM_SEC_REGISTER)
> > +               tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
> > +
> > +       if (shm->flags & TEE_SHM_REGISTER)
> > +               list_del(&shm->link);
> > +
> > +       if (shm->flags & TEE_SHM_ALLOC)
> > +               free(shm->addr);
> > +
> > +       free(shm);
> > +}
> > +
> > +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
> > +{
> > +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> > +       struct tee_shm *s;
> > +
> > +       list_for_each_entry(s, &priv->list_shm, link)
> > +               if (s == shm)
> > +                       return true;
> > +
> > +       return false;
> > +}
> > +
> > +struct udevice *tee_find_device(struct udevice *start,
> > +                               int (*match)(struct tee_version_data *vers,
> > +                                            const void *data),
> > +                               const void *data,
> > +                               struct tee_version_data *vers)
> 
> 'find' should find the device, not probe anything. Is that what this does?

It probes the device too, I'm adding that in the description of this
function. The probe is needed in order to read out the capabilities of
the TEE.

> 
> > +{
> > +       struct udevice *dev = start;
> > +       struct tee_version_data lv;
> > +       struct tee_version_data *v = vers ? vers : &lv;
> > +
> > +       if (!dev)
> > +               uclass_first_device(UCLASS_TEE, &dev);
> > +
> > +       for (; dev; uclass_next_device(&dev)) {
> > +               tee_get_ops(dev)->get_version(dev, v);
> > +               if (!match || match(v, data))
> > +                       return dev;
> > +       }
> > +
> > +       return NULL;
> > +}
> > +
> > +static int tee_pre_probe(struct udevice *dev)
> > +{
> > +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> > +
> > +       INIT_LIST_HEAD(&priv->list_shm);
> 
> blank line before return
> 
> > +       return 0;
> > +}
> > +
> > +static int tee_pre_remove(struct udevice *dev)
> > +{
> > +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> > +       struct tee_shm *shm;
> > +
> > +       while (!list_empty(&priv->list_shm)) {
> > +               shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
> > +               debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
> > +                     __func__, (void *)shm, shm->size, shm->flags);
> > +               tee_shm_free(shm);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +UCLASS_DRIVER(tee) = {
> > +       .id = UCLASS_TEE,
> > +       .name = "tee",
> > +       .per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
> > +       .pre_probe = tee_pre_probe,
> > +       .pre_remove = tee_pre_remove,
> > +};
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index a39643ec5eef..955e0a915b87 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -81,6 +81,7 @@ enum uclass_id {
> >         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
> >         UCLASS_SYSCON,          /* System configuration device */
> >         UCLASS_SYSRESET,        /* System reset device */
> > +       UCLASS_TEE,             /* Trusted Execution Environment device */
> >         UCLASS_THERMAL,         /* Thermal sensor */
> >         UCLASS_TIMER,           /* Timer device */
> >         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
> > diff --git a/include/tee.h b/include/tee.h
> > new file mode 100644
> > index 000000000000..c2ac13e34128
> > --- /dev/null
> > +++ b/include/tee.h
> > @@ -0,0 +1,134 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2018 Linaro Limited
> > + */
> > +
> > +#ifndef __TEE_H
> > +#define __TEE_H
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +
> > +#define TEE_UUID_LEN           16
> > +
> > +#define TEE_GEN_CAP_GP          BIT(0) /* GlobalPlatform compliant TEE */
> > +#define TEE_GEN_CAP_REG_MEM     BIT(1) /* Supports registering shared memory */
> > +
> > +#define TEE_SHM_REGISTER       BIT(0)
> > +#define TEE_SHM_SEC_REGISTER   BIT(1)
> > +#define TEE_SHM_ALLOC          BIT(2)
> > +
> > +#define TEE_PARAM_ATTR_TYPE_NONE               0       /* parameter not used */
> > +#define TEE_PARAM_ATTR_TYPE_VALUE_INPUT                1
> > +#define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT       2
> > +#define TEE_PARAM_ATTR_TYPE_VALUE_INOUT                3       /* input and output */
> > +#define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT       5
> > +#define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT      6
> > +#define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT       7       /* input and output */
> > +#define TEE_PARAM_ATTR_TYPE_MASK               0xff
> > +#define TEE_PARAM_ATTR_META                    0x100
> > +#define TEE_PARAM_ATTR_MASK                    (TEE_PARAM_ATTR_TYPE_MASK | \
> > +                                                TEE_PARAM_ATTR_META)
> > +
> > +/*
> > + * Some Global Platform error codes which has a meaning if the
> > + * TEE_GEN_CAP_GP bit is returned by the driver.
> > + */
> > +#define TEE_SUCCESS                    0x00000000
> > +#define TEE_ERROR_GENERIC              0xffff0000
> > +#define TEE_ERROR_BAD_PARAMETERS       0xffff0006
> > +#define TEE_ERROR_ITEM_NOT_FOUND       0xffff0008
> > +#define TEE_ERROR_NOT_IMPLEMENTED      0xffff0009
> > +#define TEE_ERROR_NOT_SUPPORTED                0xffff000a
> > +#define TEE_ERROR_COMMUNICATION                0xffff000e
> > +#define TEE_ERROR_OUT_OF_MEMORY                0xffff000c
> > +#define TEE_ERROR_TARGET_DEAD          0xffff3024
> > +
> > +#define TEE_ORIGIN_COMMS               0x00000002
> > +
> > +struct tee_driver_ops;
> > +
> > +struct tee_shm {
> 
> comments for these structs please.
> 
> Also the whole uclass needs a README or more docs. Perhaps I have missed this?

I'm sorry, didn't supply that. I'll add it in the v2.

> 
> > +       struct udevice *dev;
> > +       struct list_head link;
> > +       void *addr;
> > +       ulong size;
> > +       u32 flags;
> > +};
> > +
> > +struct tee_param_memref {
> > +       ulong shm_offs;
> > +       ulong size;
> > +       struct tee_shm *shm;
> > +};
> > +
> > +struct tee_param_value {
> > +       u64 a;
> > +       u64 b;
> > +       u64 c;
> > +};
> > +
> > +struct tee_param {
> > +       u64 attr;
> > +       union {
> > +               struct tee_param_memref memref;
> > +               struct tee_param_value value;
> > +       } u;
> > +};
> > +
> > +struct tee_open_session_arg {
> > +       u8 uuid[TEE_UUID_LEN];
> > +       u8 clnt_uuid[TEE_UUID_LEN];
> > +       u32 clnt_login;
> > +       u32 session;
> > +       u32 ret;
> > +       u32 ret_origin;
> > +};
> > +
> > +struct tee_invoke_arg {
> > +       u32 func;
> > +       u32 session;
> > +       u32 ret;
> > +       u32 ret_origin;
> > +};
> > +
> > +struct tee_version_data {
> > +       u32 gen_caps;
> > +};
> > +
> > +struct tee_driver_ops {
> > +       void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
> > +       int (*open_session)(struct udevice *dev,
> > +                           struct tee_open_session_arg *arg, ulong num_param,
> > +                           struct tee_param *param);
> > +       int (*close_session)(struct udevice *dev, u32 session);
> > +       int (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
> > +                          ulong num_param, struct tee_param *param);
> > +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
> > +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
> 
> Each of these needs a full function comment. Without that I cannot
> really comment on the API. Same for functions below.

OK

> 
> > +};
> > +
> > +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> > +                             ulong size, u32 flags);
> > +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);
> > +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> > +                                ulong length, u32 flags);
> > +void tee_shm_free(struct tee_shm *shm);
> > +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
> > +
> > +struct udevice *tee_find_device(struct udevice *start,
> > +                               int (*match)(struct tee_version_data *vers,
> > +                                            const void *data),
> > +                               const void *data,
> > +                               struct tee_version_data *vers);
> > +
> > +void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
> > +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> > +                    ulong num_param, struct tee_param *param);
> > +
> > +int tee_close_session(struct udevice *dev, u32 session);
> > +
> > +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> > +                   ulong num_param, struct tee_param *param);
> > +
> > +#endif /*__TEE_H*/
> > --
> > 2.17.1
> >

Thanks for the review. I'll address all the comments in the comming v2
patch set.

--
Jens

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-08-16 12:13   ` Igor Opaniuk
@ 2018-08-22 13:52     ` Jens Wiklander
  0 siblings, 0 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-22 13:52 UTC (permalink / raw)
  To: u-boot

Hi Igor,

On Thu, Aug 16, 2018 at 2:13 PM, Igor Opaniuk <igor.opaniuk@linaro.org> wrote:
> As I didn't have any available Hikey board, tested this on Poplar:
>
> Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
>
> BTW, we've had it up for discussion already, but just to clarify and summarize:
> As ID of eMMC is hardcoded in the OP-TEE OS core (CFG_RPMB_FS_DEV_ID),
> we will probably have issues on some platforms, where there is a
> difference in the probe order of MMC controllers (for example, on
> Poplar eMMC is 0 in U-boot, but in Linux it's 1, as SD is enumerated
> as 0).
> I guess it's unlikely that people will introduce changes to
> U-boot/Linux to make this order conform to each other, so instead, we
> should let the Normal World-part to decide what eMMC id to use from
> these RPMB frames.

Both U-boot and Linux are part of Normal World. I guess you're
suggesting to move the logic of selecting RPMB device based on the ID
from Secure World to tee-supplicant. For Linux that's a user space
daemon and in U-boot that's part of the OP-TEE driver. I think it
would be unfortunate to have this logic in user space, upgrades can
make a mess of this.

This is in one aspect a board specific problem which can be addressed
by defining the sequence number (what's indicated by
CFG_RPMB_FS_DEV_ID above) of relevant RPMB partitions on a specific
board. This is what we have been relying on indirectly so far.

Another way to deal with this problem is to let Secure World probe all
available RPMB partitions and use the one using the expected shared
secret for MACing. A drawback is that it's more complicated in Secure
World and will take a while before it's implemented.

Thanks,
Jens

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 00/10] AVB using OP-TEE
  2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
                   ` (9 preceding siblings ...)
  2018-08-13 15:53 ` [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB Jens Wiklander
@ 2018-08-23 10:45 ` Simon Glass
  2018-08-23 11:23   ` Jens Wiklander
  10 siblings, 1 reply; 40+ messages in thread
From: Simon Glass @ 2018-08-23 10:45 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Hi,
>
> This adds support for storing AVB rollback indexes in the RPMB partition.
> The RPMB partition (content and key) is managed by OP-TEE
> (https://www.op-tee.org/) which is a secure OS leveraging ARM TrustZone.
>
> The Linux kernel can already support OP-TEE with reading and updating
> rollback indexes in the RPMB partition, the catch is that this is needed
> before the kernel has booted.
>
> The design here is the same as what is in the Linux kernel, with the
> exception that the user space daemon tee-supplicant is integrated in the
> OP-TEE driver here (drivers/tee/optee/supplicant.c) instead. A new uclass
> (UCLASS_TEE) is introduced to provide an abstraction for interfacing with a
> Trusted Execution Environment (TEE). There's also the OP-TEE driver using
> UCLASS_TEE for registration.
>
> A Trusted Application (TA) interface is added to be used by the AVB verify
> functions which are updated accordingly. The TA is managed by OP-TEE and is
> executed in a secure TrustZone protected environment.
>
> The header files drivers/tee/optee/optee_{msg,msg_supplicant,smc}.h and
> include/tee/optee_ta_avb.h are copied from
> https://github.com/OP-TEE/optee_os/tree/master more or less unmodified.
> They may need to be updated from time to time in order to support new
> features.
>
> In MMC there's a new function, mmc_rpmb_route_frames(), which as the name
> suggests is used to route RPMB frames to/from the MMC. This saves OP-TEE
> from implementing an MMC driver which would need to share resources with
> its counterpart here in U-boot.
>
> This was tested on a Hikey (Kirin 620) board.
>
> I've added myself as maintainer of the TEE stuff.
>
> Thanks,
> Jens
>
> Jens Wiklander (10):
>   dm: fdt: scan for devices under /firmware too
>   cmd: avb read_rb: print rb_idx in hexadecimal
>   mmc: rpmb: add mmc_rpmb_route_frames()
>   Add UCLASS_TEE for Trusted Execution Environment
>   dt/bindings: add bindings for optee
>   tee: add OP-TEE driver
>   arm: dt: hikey: Add optee node
>   optee: support routing of rpmb data frames to mmc
>   tee: optee: support AVB trusted application
>   avb_verify: support using OP-TEE TA AVB
>
>  MAINTAINERS                                   |   7 +
>  arch/arm/dts/hi6220-hikey.dts                 |   7 +
>  cmd/avb.c                                     |   2 +-
>  common/avb_verify.c                           | 132 +++-
>  .../firmware/linaro,optee-tz.txt              |  31 +
>  drivers/Kconfig                               |   2 +
>  drivers/Makefile                              |   1 +
>  drivers/core/root.c                           |  15 +-
>  drivers/mmc/rpmb.c                            | 160 +++++
>  drivers/tee/Kconfig                           |  18 +
>  drivers/tee/Makefile                          |   4 +
>  drivers/tee/optee/Kconfig                     |  23 +
>  drivers/tee/optee/Makefile                    |   5 +
>  drivers/tee/optee/core.c                      | 622 ++++++++++++++++++
>  drivers/tee/optee/optee_msg.h                 | 423 ++++++++++++
>  drivers/tee/optee/optee_msg_supplicant.h      | 234 +++++++
>  drivers/tee/optee/optee_private.h             |  41 ++
>  drivers/tee/optee/optee_smc.h                 | 444 +++++++++++++
>  drivers/tee/optee/rpmb.c                      | 184 ++++++
>  drivers/tee/optee/supplicant.c                |  92 +++
>  drivers/tee/tee-uclass.c                      | 180 +++++
>  include/avb_verify.h                          |   4 +
>  include/dm/uclass-id.h                        |   1 +
>  include/mmc.h                                 |   2 +
>  include/tee.h                                 | 141 ++++
>  include/tee/optee_ta_avb.h                    |  48 ++
>  26 files changed, 2816 insertions(+), 7 deletions(-)
>  create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt
>  create mode 100644 drivers/tee/Kconfig
>  create mode 100644 drivers/tee/Makefile
>  create mode 100644 drivers/tee/optee/Kconfig
>  create mode 100644 drivers/tee/optee/Makefile
>  create mode 100644 drivers/tee/optee/core.c
>  create mode 100644 drivers/tee/optee/optee_msg.h
>  create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
>  create mode 100644 drivers/tee/optee/optee_private.h
>  create mode 100644 drivers/tee/optee/optee_smc.h
>  create mode 100644 drivers/tee/optee/rpmb.c
>  create mode 100644 drivers/tee/optee/supplicant.c
>  create mode 100644 drivers/tee/tee-uclass.c
>  create mode 100644 include/tee.h
>  create mode 100644 include/tee/optee_ta_avb.h
>
> --
> 2.17.1
>

I missed the Android Verified Boot stuff going in. I did see the v1
patch but not the v2.

Was there discussion of coding style for lib/libavb?

Also, how is this stuff tested in U-Boot? I don't see any tests.

For the uclass, please add a sandbox driver and test even if there are
no other tests.

Regards,
Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-13 15:53 ` [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
  2018-08-16 12:14   ` Igor Opaniuk
  2018-08-17 12:48   ` Simon Glass
@ 2018-08-23 10:45   ` Simon Glass
  2018-08-23 11:11     ` Jens Wiklander
  2 siblings, 1 reply; 40+ messages in thread
From: Simon Glass @ 2018-08-23 10:45 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds a uclass to interface with a TEE (Trusted Execution Environment).
>
> A TEE driver is a driver that interfaces with a trusted OS running in
> some secure environment, for example, TrustZone on ARM cpus, or a
> separate secure co-processor etc.
>
> The TEE subsystem can serve a TEE driver for a Global Platform compliant
> TEE, but it's not limited to only Global Platform TEEs.
>
> The over all design is based on the TEE subsystem in the Linux kernel,
> tailored for U-boot.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  MAINTAINERS              |   6 ++
>  drivers/Kconfig          |   2 +
>  drivers/Makefile         |   1 +
>  drivers/tee/Kconfig      |   8 ++
>  drivers/tee/Makefile     |   3 +
>  drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
>  include/dm/uclass-id.h   |   1 +
>  include/tee.h            | 134 +++++++++++++++++++++++++++++
>  8 files changed, 335 insertions(+)
>  create mode 100644 drivers/tee/Kconfig
>  create mode 100644 drivers/tee/Makefile
>  create mode 100644 drivers/tee/tee-uclass.c
>  create mode 100644 include/tee.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 58b61ac05882..7458c606ee92 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -571,6 +571,12 @@ TQ GROUP
>  S:     Orphaned (Since 2016-02)
>  T:     git git://git.denx.de/u-boot-tq-group.git
>
> +TEE
> +M:     Jens Wiklander <jens.wiklander@linaro.org>
> +S:     Maintained
> +F:     drivers/tee/
> +F:     include/tee.h
> +
>  UBI
>  M:     Kyungmin Park <kmpark@infradead.org>
>  M:     Heiko Schocher <hs@denx.de>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c72abf893297..f3249ab1d143 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
>
>  source "drivers/sysreset/Kconfig"
>
> +source "drivers/tee/Kconfig"
> +
>  source "drivers/thermal/Kconfig"
>
>  source "drivers/timer/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index d53208540ea6..0fcae36f50f7 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -103,6 +103,7 @@ obj-y += smem/
>  obj-y += soc/
>  obj-$(CONFIG_REMOTEPROC) += remoteproc/
>  obj-y += thermal/
> +obj-$(CONFIG_TEE) += tee/
>
>  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
>  endif
> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
> new file mode 100644
> index 000000000000..817ab331b0f8
> --- /dev/null
> +++ b/drivers/tee/Kconfig
> @@ -0,0 +1,8 @@
> +# Generic Trusted Execution Environment Configuration
> +config TEE
> +       bool "Trusted Execution Environment support"
> +       depends on ARM && (ARM64 || CPU_V7A)
> +       select ARM_SMCCC
> +       help
> +         This implements a generic interface towards a Trusted Execution
> +         Environment (TEE).
> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> new file mode 100644
> index 000000000000..b6d8e16e6211
> --- /dev/null
> +++ b/drivers/tee/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +obj-y += tee-uclass.o
> diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
> new file mode 100644
> index 000000000000..f0243a0f2e4e
> --- /dev/null
> +++ b/drivers/tee/tee-uclass.c
> @@ -0,0 +1,180 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <tee.h>
> +
> +struct tee_uclass_priv {
> +       struct list_head list_shm;
> +};
> +
> +static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
> +{
> +       return device_get_ops(dev);
> +}
> +
> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
> +{
> +       tee_get_ops(dev)->get_version(dev, vers);
> +}
> +
> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> +                    ulong num_param, struct tee_param *param)
> +{
> +       return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
> +}
> +
> +int tee_close_session(struct udevice *dev, u32 session)
> +{
> +       return tee_get_ops(dev)->close_session(dev, session);
> +}
> +
> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                   ulong num_param, struct tee_param *param)
> +{
> +       return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
> +}
> +
> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> +                             ulong size, u32 flags)
> +{
> +       struct tee_shm *shm;
> +       void *p = addr;
> +
> +       if (flags & TEE_SHM_ALLOC) {
> +               if (align)
> +                       p = memalign(align, size);
> +               else
> +                       p = malloc(size);
> +       }
> +       if (!p)
> +               return NULL;
> +
> +       shm = calloc(1, sizeof(*shm));
> +       if (!shm)
> +               goto err;
> +
> +       shm->dev = dev;
> +       shm->addr = p;
> +       shm->size = size;
> +       shm->flags = flags;
> +
> +       if ((flags & TEE_SHM_SEC_REGISTER) &&
> +           tee_get_ops(dev)->shm_register(dev, shm))
> +               goto err;

It seems like this can return errors other than -ENOMEM. How about
changing this function to return an int?

> +
> +       if (flags & TEE_SHM_REGISTER) {
> +               struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +
> +               list_add(&shm->link, &priv->list_shm);
> +       }
> +       return shm;
> +err:
> +       free(shm);
> +       if (flags & TEE_SHM_ALLOC)
> +               free(p);
> +       return NULL;
> +}
> +
> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
> +                             u32 flags)
> +{
> +       u32 f = flags;
> +
> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;

blank line before return

> +       return __tee_shm_add(dev, 0, NULL, size, f);
> +}
> +
> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> +                                ulong size, u32 flags)
> +{
> +       u32 f = flags & ~TEE_SHM_ALLOC;
> +
> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
> +       return __tee_shm_add(dev, 0, addr, size, f);
> +}
> +
> +void tee_shm_free(struct tee_shm *shm)
> +{
> +       if (!shm)
> +               return;
> +
> +       if (shm->flags & TEE_SHM_SEC_REGISTER)
> +               tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
> +
> +       if (shm->flags & TEE_SHM_REGISTER)
> +               list_del(&shm->link);
> +
> +       if (shm->flags & TEE_SHM_ALLOC)
> +               free(shm->addr);
> +
> +       free(shm);
> +}
> +
> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +       struct tee_shm *s;
> +
> +       list_for_each_entry(s, &priv->list_shm, link)
> +               if (s == shm)
> +                       return true;
> +
> +       return false;
> +}
> +
> +struct udevice *tee_find_device(struct udevice *start,
> +                               int (*match)(struct tee_version_data *vers,
> +                                            const void *data),
> +                               const void *data,
> +                               struct tee_version_data *vers)
> +{
> +       struct udevice *dev = start;
> +       struct tee_version_data lv;
> +       struct tee_version_data *v = vers ? vers : &lv;
> +
> +       if (!dev)
> +               uclass_first_device(UCLASS_TEE, &dev);
> +
> +       for (; dev; uclass_next_device(&dev)) {
> +               tee_get_ops(dev)->get_version(dev, v);
> +               if (!match || match(v, data))
> +                       return dev;

This will probe each device as it looks through them. Is that what you want?

> +       }
> +
> +       return NULL;
> +}
> +
> +static int tee_pre_probe(struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +
> +       INIT_LIST_HEAD(&priv->list_shm);
> +       return 0;
> +}
> +
> +static int tee_pre_remove(struct udevice *dev)
> +{
> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
> +       struct tee_shm *shm;
> +
> +       while (!list_empty(&priv->list_shm)) {
> +               shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
> +               debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
> +                     __func__, (void *)shm, shm->size, shm->flags);
> +               tee_shm_free(shm);
> +       }
> +
> +       return 0;
> +}
> +
> +UCLASS_DRIVER(tee) = {
> +       .id = UCLASS_TEE,
> +       .name = "tee",
> +       .per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
> +       .pre_probe = tee_pre_probe,
> +       .pre_remove = tee_pre_remove,
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a39643ec5eef..955e0a915b87 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -81,6 +81,7 @@ enum uclass_id {
>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>         UCLASS_SYSCON,          /* System configuration device */
>         UCLASS_SYSRESET,        /* System reset device */
> +       UCLASS_TEE,             /* Trusted Execution Environment device */

We need a bit more information about what this is for. It could go in
a README or in the uclass header file.

>         UCLASS_THERMAL,         /* Thermal sensor */
>         UCLASS_TIMER,           /* Timer device */
>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
> diff --git a/include/tee.h b/include/tee.h
> new file mode 100644
> index 000000000000..c2ac13e34128
> --- /dev/null
> +++ b/include/tee.h
> @@ -0,0 +1,134 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#ifndef __TEE_H
> +#define __TEE_H
> +
> +#include <common.h>
> +#include <dm.h>

These should be included by .c files.

> +
> +#define TEE_UUID_LEN           16
> +
> +#define TEE_GEN_CAP_GP          BIT(0) /* GlobalPlatform compliant TEE */
> +#define TEE_GEN_CAP_REG_MEM     BIT(1) /* Supports registering shared memory */
> +
> +#define TEE_SHM_REGISTER       BIT(0)
> +#define TEE_SHM_SEC_REGISTER   BIT(1)
> +#define TEE_SHM_ALLOC          BIT(2)
> +
> +#define TEE_PARAM_ATTR_TYPE_NONE               0       /* parameter not used */
> +#define TEE_PARAM_ATTR_TYPE_VALUE_INPUT                1
> +#define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT       2
> +#define TEE_PARAM_ATTR_TYPE_VALUE_INOUT                3       /* input and output */
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT       5
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT      6
> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT       7       /* input and output */
> +#define TEE_PARAM_ATTR_TYPE_MASK               0xff
> +#define TEE_PARAM_ATTR_META                    0x100
> +#define TEE_PARAM_ATTR_MASK                    (TEE_PARAM_ATTR_TYPE_MASK | \
> +                                                TEE_PARAM_ATTR_META)
> +
> +/*
> + * Some Global Platform error codes which has a meaning if the
> + * TEE_GEN_CAP_GP bit is returned by the driver.
> + */
> +#define TEE_SUCCESS                    0x00000000
> +#define TEE_ERROR_GENERIC              0xffff0000
> +#define TEE_ERROR_BAD_PARAMETERS       0xffff0006
> +#define TEE_ERROR_ITEM_NOT_FOUND       0xffff0008
> +#define TEE_ERROR_NOT_IMPLEMENTED      0xffff0009
> +#define TEE_ERROR_NOT_SUPPORTED                0xffff000a
> +#define TEE_ERROR_COMMUNICATION                0xffff000e
> +#define TEE_ERROR_OUT_OF_MEMORY                0xffff000c
> +#define TEE_ERROR_TARGET_DEAD          0xffff3024
> +
> +#define TEE_ORIGIN_COMMS               0x00000002
> +
> +struct tee_driver_ops;
> +
> +struct tee_shm {

Comment structure, and below

> +       struct udevice *dev;
> +       struct list_head link;
> +       void *addr;
> +       ulong size;
> +       u32 flags;
> +};
> +
> +struct tee_param_memref {
> +       ulong shm_offs;
> +       ulong size;
> +       struct tee_shm *shm;
> +};
> +
> +struct tee_param_value {
> +       u64 a;
> +       u64 b;
> +       u64 c;
> +};
> +
> +struct tee_param {
> +       u64 attr;
> +       union {
> +               struct tee_param_memref memref;
> +               struct tee_param_value value;
> +       } u;
> +};
> +
> +struct tee_open_session_arg {
> +       u8 uuid[TEE_UUID_LEN];
> +       u8 clnt_uuid[TEE_UUID_LEN];
> +       u32 clnt_login;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +struct tee_invoke_arg {
> +       u32 func;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +struct tee_version_data {
> +       u32 gen_caps;
> +};
> +
> +struct tee_driver_ops {

These all need full comments.

> +       void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
> +       int (*open_session)(struct udevice *dev,
> +                           struct tee_open_session_arg *arg, ulong num_param,
> +                           struct tee_param *param);
> +       int (*close_session)(struct udevice *dev, u32 session);
> +       int (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
> +                          ulong num_param, struct tee_param *param);
> +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
> +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
> +};
> +

And these

> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
> +                             ulong size, u32 flags);
> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);

What are flags? All of this needs documentation please.

> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
> +                                ulong length, u32 flags);
> +void tee_shm_free(struct tee_shm *shm);
> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
> +
> +struct udevice *tee_find_device(struct udevice *start,
> +                               int (*match)(struct tee_version_data *vers,
> +                                            const void *data),
> +                               const void *data,
> +                               struct tee_version_data *vers);
> +
> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
> +                    ulong num_param, struct tee_param *param);
> +
> +int tee_close_session(struct udevice *dev, u32 session);
> +
> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
> +                   ulong num_param, struct tee_param *param);
> +
> +#endif /*__TEE_H*/
> --
> 2.17.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-23 10:45   ` Simon Glass
@ 2018-08-23 11:11     ` Jens Wiklander
  2018-08-23 16:31       ` Simon Glass
  0 siblings, 1 reply; 40+ messages in thread
From: Jens Wiklander @ 2018-08-23 11:11 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, Aug 23, 2018 at 12:45 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Jens,
>
> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> Adds a uclass to interface with a TEE (Trusted Execution Environment).
>>
>> A TEE driver is a driver that interfaces with a trusted OS running in
>> some secure environment, for example, TrustZone on ARM cpus, or a
>> separate secure co-processor etc.
>>
>> The TEE subsystem can serve a TEE driver for a Global Platform compliant
>> TEE, but it's not limited to only Global Platform TEEs.
>>
>> The over all design is based on the TEE subsystem in the Linux kernel,
>> tailored for U-boot.
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  MAINTAINERS              |   6 ++
>>  drivers/Kconfig          |   2 +
>>  drivers/Makefile         |   1 +
>>  drivers/tee/Kconfig      |   8 ++
>>  drivers/tee/Makefile     |   3 +
>>  drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
>>  include/dm/uclass-id.h   |   1 +
>>  include/tee.h            | 134 +++++++++++++++++++++++++++++
>>  8 files changed, 335 insertions(+)
>>  create mode 100644 drivers/tee/Kconfig
>>  create mode 100644 drivers/tee/Makefile
>>  create mode 100644 drivers/tee/tee-uclass.c
>>  create mode 100644 include/tee.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 58b61ac05882..7458c606ee92 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -571,6 +571,12 @@ TQ GROUP
>>  S:     Orphaned (Since 2016-02)
>>  T:     git git://git.denx.de/u-boot-tq-group.git
>>
>> +TEE
>> +M:     Jens Wiklander <jens.wiklander@linaro.org>
>> +S:     Maintained
>> +F:     drivers/tee/
>> +F:     include/tee.h
>> +
>>  UBI
>>  M:     Kyungmin Park <kmpark@infradead.org>
>>  M:     Heiko Schocher <hs@denx.de>
>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>> index c72abf893297..f3249ab1d143 100644
>> --- a/drivers/Kconfig
>> +++ b/drivers/Kconfig
>> @@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
>>
>>  source "drivers/sysreset/Kconfig"
>>
>> +source "drivers/tee/Kconfig"
>> +
>>  source "drivers/thermal/Kconfig"
>>
>>  source "drivers/timer/Kconfig"
>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index d53208540ea6..0fcae36f50f7 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -103,6 +103,7 @@ obj-y += smem/
>>  obj-y += soc/
>>  obj-$(CONFIG_REMOTEPROC) += remoteproc/
>>  obj-y += thermal/
>> +obj-$(CONFIG_TEE) += tee/
>>
>>  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
>>  endif
>> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
>> new file mode 100644
>> index 000000000000..817ab331b0f8
>> --- /dev/null
>> +++ b/drivers/tee/Kconfig
>> @@ -0,0 +1,8 @@
>> +# Generic Trusted Execution Environment Configuration
>> +config TEE
>> +       bool "Trusted Execution Environment support"
>> +       depends on ARM && (ARM64 || CPU_V7A)
>> +       select ARM_SMCCC
>> +       help
>> +         This implements a generic interface towards a Trusted Execution
>> +         Environment (TEE).
>> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
>> new file mode 100644
>> index 000000000000..b6d8e16e6211
>> --- /dev/null
>> +++ b/drivers/tee/Makefile
>> @@ -0,0 +1,3 @@
>> +# SPDX-License-Identifier: GPL-2.0+
>> +
>> +obj-y += tee-uclass.o
>> diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
>> new file mode 100644
>> index 000000000000..f0243a0f2e4e
>> --- /dev/null
>> +++ b/drivers/tee/tee-uclass.c
>> @@ -0,0 +1,180 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (c) 2018 Linaro Limited
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <tee.h>
>> +
>> +struct tee_uclass_priv {
>> +       struct list_head list_shm;
>> +};
>> +
>> +static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
>> +{
>> +       return device_get_ops(dev);
>> +}
>> +
>> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
>> +{
>> +       tee_get_ops(dev)->get_version(dev, vers);
>> +}
>> +
>> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
>> +                    ulong num_param, struct tee_param *param)
>> +{
>> +       return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
>> +}
>> +
>> +int tee_close_session(struct udevice *dev, u32 session)
>> +{
>> +       return tee_get_ops(dev)->close_session(dev, session);
>> +}
>> +
>> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
>> +                   ulong num_param, struct tee_param *param)
>> +{
>> +       return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
>> +}
>> +
>> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
>> +                             ulong size, u32 flags)
>> +{
>> +       struct tee_shm *shm;
>> +       void *p = addr;
>> +
>> +       if (flags & TEE_SHM_ALLOC) {
>> +               if (align)
>> +                       p = memalign(align, size);
>> +               else
>> +                       p = malloc(size);
>> +       }
>> +       if (!p)
>> +               return NULL;
>> +
>> +       shm = calloc(1, sizeof(*shm));
>> +       if (!shm)
>> +               goto err;
>> +
>> +       shm->dev = dev;
>> +       shm->addr = p;
>> +       shm->size = size;
>> +       shm->flags = flags;
>> +
>> +       if ((flags & TEE_SHM_SEC_REGISTER) &&
>> +           tee_get_ops(dev)->shm_register(dev, shm))
>> +               goto err;
>
> It seems like this can return errors other than -ENOMEM. How about
> changing this function to return an int?

OK, I'll fix.

>
>> +
>> +       if (flags & TEE_SHM_REGISTER) {
>> +               struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>> +
>> +               list_add(&shm->link, &priv->list_shm);
>> +       }
>> +       return shm;
>> +err:
>> +       free(shm);
>> +       if (flags & TEE_SHM_ALLOC)
>> +               free(p);
>> +       return NULL;
>> +}
>> +
>> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
>> +                             u32 flags)
>> +{
>> +       u32 f = flags;
>> +
>> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
>
> blank line before return

OK

>
>> +       return __tee_shm_add(dev, 0, NULL, size, f);
>> +}
>> +
>> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
>> +                                ulong size, u32 flags)
>> +{
>> +       u32 f = flags & ~TEE_SHM_ALLOC;
>> +
>> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
>> +       return __tee_shm_add(dev, 0, addr, size, f);
>> +}
>> +
>> +void tee_shm_free(struct tee_shm *shm)
>> +{
>> +       if (!shm)
>> +               return;
>> +
>> +       if (shm->flags & TEE_SHM_SEC_REGISTER)
>> +               tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
>> +
>> +       if (shm->flags & TEE_SHM_REGISTER)
>> +               list_del(&shm->link);
>> +
>> +       if (shm->flags & TEE_SHM_ALLOC)
>> +               free(shm->addr);
>> +
>> +       free(shm);
>> +}
>> +
>> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
>> +{
>> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>> +       struct tee_shm *s;
>> +
>> +       list_for_each_entry(s, &priv->list_shm, link)
>> +               if (s == shm)
>> +                       return true;
>> +
>> +       return false;
>> +}
>> +
>> +struct udevice *tee_find_device(struct udevice *start,
>> +                               int (*match)(struct tee_version_data *vers,
>> +                                            const void *data),
>> +                               const void *data,
>> +                               struct tee_version_data *vers)
>> +{
>> +       struct udevice *dev = start;
>> +       struct tee_version_data lv;
>> +       struct tee_version_data *v = vers ? vers : &lv;
>> +
>> +       if (!dev)
>> +               uclass_first_device(UCLASS_TEE, &dev);
>> +
>> +       for (; dev; uclass_next_device(&dev)) {
>> +               tee_get_ops(dev)->get_version(dev, v);
>> +               if (!match || match(v, data))
>> +                       return dev;
>
> This will probe each device as it looks through them. Is that what you want?

Yes, in practice there will be only one or perhaps in some special
cases two. The capabilities reported by secure world are needed tee.

>
>> +       }
>> +
>> +       return NULL;
>> +}
>> +
>> +static int tee_pre_probe(struct udevice *dev)
>> +{
>> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>> +
>> +       INIT_LIST_HEAD(&priv->list_shm);
>> +       return 0;
>> +}
>> +
>> +static int tee_pre_remove(struct udevice *dev)
>> +{
>> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>> +       struct tee_shm *shm;
>> +
>> +       while (!list_empty(&priv->list_shm)) {
>> +               shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
>> +               debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
>> +                     __func__, (void *)shm, shm->size, shm->flags);
>> +               tee_shm_free(shm);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +UCLASS_DRIVER(tee) = {
>> +       .id = UCLASS_TEE,
>> +       .name = "tee",
>> +       .per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
>> +       .pre_probe = tee_pre_probe,
>> +       .pre_remove = tee_pre_remove,
>> +};
>> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>> index a39643ec5eef..955e0a915b87 100644
>> --- a/include/dm/uclass-id.h
>> +++ b/include/dm/uclass-id.h
>> @@ -81,6 +81,7 @@ enum uclass_id {
>>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>>         UCLASS_SYSCON,          /* System configuration device */
>>         UCLASS_SYSRESET,        /* System reset device */
>> +       UCLASS_TEE,             /* Trusted Execution Environment device */
>
> We need a bit more information about what this is for. It could go in
> a README or in the uclass header file.
>
>>         UCLASS_THERMAL,         /* Thermal sensor */
>>         UCLASS_TIMER,           /* Timer device */
>>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
>> diff --git a/include/tee.h b/include/tee.h
>> new file mode 100644
>> index 000000000000..c2ac13e34128
>> --- /dev/null
>> +++ b/include/tee.h
>> @@ -0,0 +1,134 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * Copyright (c) 2018 Linaro Limited
>> + */
>> +
>> +#ifndef __TEE_H
>> +#define __TEE_H
>> +
>> +#include <common.h>
>> +#include <dm.h>
>
> These should be included by .c files.

Yes, but what those provides is also needed by this .h file.
Aren't all .h files supposed to include what they depend on?

>
>> +
>> +#define TEE_UUID_LEN           16
>> +
>> +#define TEE_GEN_CAP_GP          BIT(0) /* GlobalPlatform compliant TEE */
>> +#define TEE_GEN_CAP_REG_MEM     BIT(1) /* Supports registering shared memory */
>> +
>> +#define TEE_SHM_REGISTER       BIT(0)
>> +#define TEE_SHM_SEC_REGISTER   BIT(1)
>> +#define TEE_SHM_ALLOC          BIT(2)
>> +
>> +#define TEE_PARAM_ATTR_TYPE_NONE               0       /* parameter not used */
>> +#define TEE_PARAM_ATTR_TYPE_VALUE_INPUT                1
>> +#define TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT       2
>> +#define TEE_PARAM_ATTR_TYPE_VALUE_INOUT                3       /* input and output */
>> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INPUT       5
>> +#define TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT      6
>> +#define TEE_PARAM_ATTR_TYPE_MEMREF_INOUT       7       /* input and output */
>> +#define TEE_PARAM_ATTR_TYPE_MASK               0xff
>> +#define TEE_PARAM_ATTR_META                    0x100
>> +#define TEE_PARAM_ATTR_MASK                    (TEE_PARAM_ATTR_TYPE_MASK | \
>> +                                                TEE_PARAM_ATTR_META)
>> +
>> +/*
>> + * Some Global Platform error codes which has a meaning if the
>> + * TEE_GEN_CAP_GP bit is returned by the driver.
>> + */
>> +#define TEE_SUCCESS                    0x00000000
>> +#define TEE_ERROR_GENERIC              0xffff0000
>> +#define TEE_ERROR_BAD_PARAMETERS       0xffff0006
>> +#define TEE_ERROR_ITEM_NOT_FOUND       0xffff0008
>> +#define TEE_ERROR_NOT_IMPLEMENTED      0xffff0009
>> +#define TEE_ERROR_NOT_SUPPORTED                0xffff000a
>> +#define TEE_ERROR_COMMUNICATION                0xffff000e
>> +#define TEE_ERROR_OUT_OF_MEMORY                0xffff000c
>> +#define TEE_ERROR_TARGET_DEAD          0xffff3024
>> +
>> +#define TEE_ORIGIN_COMMS               0x00000002
>> +
>> +struct tee_driver_ops;
>> +
>> +struct tee_shm {
>
> Comment structure, and below

I've added that in the V2 that I posted as you replied here.

>
>> +       struct udevice *dev;
>> +       struct list_head link;
>> +       void *addr;
>> +       ulong size;
>> +       u32 flags;
>> +};
>> +
>> +struct tee_param_memref {
>> +       ulong shm_offs;
>> +       ulong size;
>> +       struct tee_shm *shm;
>> +};
>> +
>> +struct tee_param_value {
>> +       u64 a;
>> +       u64 b;
>> +       u64 c;
>> +};
>> +
>> +struct tee_param {
>> +       u64 attr;
>> +       union {
>> +               struct tee_param_memref memref;
>> +               struct tee_param_value value;
>> +       } u;
>> +};
>> +
>> +struct tee_open_session_arg {
>> +       u8 uuid[TEE_UUID_LEN];
>> +       u8 clnt_uuid[TEE_UUID_LEN];
>> +       u32 clnt_login;
>> +       u32 session;
>> +       u32 ret;
>> +       u32 ret_origin;
>> +};
>> +
>> +struct tee_invoke_arg {
>> +       u32 func;
>> +       u32 session;
>> +       u32 ret;
>> +       u32 ret_origin;
>> +};
>> +
>> +struct tee_version_data {
>> +       u32 gen_caps;
>> +};
>> +
>> +struct tee_driver_ops {
>
> These all need full comments.
>
>> +       void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
>> +       int (*open_session)(struct udevice *dev,
>> +                           struct tee_open_session_arg *arg, ulong num_param,
>> +                           struct tee_param *param);
>> +       int (*close_session)(struct udevice *dev, u32 session);
>> +       int (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
>> +                          ulong num_param, struct tee_param *param);
>> +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
>> +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
>> +};
>> +
>
> And these
>
>> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
>> +                             ulong size, u32 flags);
>> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);
>
> What are flags? All of this needs documentation please.
>
>> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
>> +                                ulong length, u32 flags);
>> +void tee_shm_free(struct tee_shm *shm);
>> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
>> +
>> +struct udevice *tee_find_device(struct udevice *start,
>> +                               int (*match)(struct tee_version_data *vers,
>> +                                            const void *data),
>> +                               const void *data,
>> +                               struct tee_version_data *vers);
>> +
>> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
>> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
>> +                    ulong num_param, struct tee_param *param);
>> +
>> +int tee_close_session(struct udevice *dev, u32 session);
>> +
>> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
>> +                   ulong num_param, struct tee_param *param);
>> +
>> +#endif /*__TEE_H*/
>> --
>> 2.17.1
>>

Thanks for the review. I posted V2 of this patch set at the same time
as you replied, I'll address what's not already done in V2 in the
coming V3.

--
Jens

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 00/10] AVB using OP-TEE
  2018-08-23 10:45 ` [U-Boot] [PATCH 00/10] AVB using OP-TEE Simon Glass
@ 2018-08-23 11:23   ` Jens Wiklander
  2018-08-23 12:15     ` Igor Opaniuk
  2018-08-23 16:31     ` Simon Glass
  0 siblings, 2 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-23 11:23 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, Aug 23, 2018 at 12:45 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Jens,
>
> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> Hi,
>>
>> This adds support for storing AVB rollback indexes in the RPMB partition.
>> The RPMB partition (content and key) is managed by OP-TEE
>> (https://www.op-tee.org/) which is a secure OS leveraging ARM TrustZone.
>>
>> The Linux kernel can already support OP-TEE with reading and updating
>> rollback indexes in the RPMB partition, the catch is that this is needed
>> before the kernel has booted.
>>
>> The design here is the same as what is in the Linux kernel, with the
>> exception that the user space daemon tee-supplicant is integrated in the
>> OP-TEE driver here (drivers/tee/optee/supplicant.c) instead. A new uclass
>> (UCLASS_TEE) is introduced to provide an abstraction for interfacing with a
>> Trusted Execution Environment (TEE). There's also the OP-TEE driver using
>> UCLASS_TEE for registration.
>>
>> A Trusted Application (TA) interface is added to be used by the AVB verify
>> functions which are updated accordingly. The TA is managed by OP-TEE and is
>> executed in a secure TrustZone protected environment.
>>
>> The header files drivers/tee/optee/optee_{msg,msg_supplicant,smc}.h and
>> include/tee/optee_ta_avb.h are copied from
>> https://github.com/OP-TEE/optee_os/tree/master more or less unmodified.
>> They may need to be updated from time to time in order to support new
>> features.
>>
>> In MMC there's a new function, mmc_rpmb_route_frames(), which as the name
>> suggests is used to route RPMB frames to/from the MMC. This saves OP-TEE
>> from implementing an MMC driver which would need to share resources with
>> its counterpart here in U-boot.
>>
>> This was tested on a Hikey (Kirin 620) board.
>>
>> I've added myself as maintainer of the TEE stuff.
>>
>> Thanks,
>> Jens
>>
>> Jens Wiklander (10):
>>   dm: fdt: scan for devices under /firmware too
>>   cmd: avb read_rb: print rb_idx in hexadecimal
>>   mmc: rpmb: add mmc_rpmb_route_frames()
>>   Add UCLASS_TEE for Trusted Execution Environment
>>   dt/bindings: add bindings for optee
>>   tee: add OP-TEE driver
>>   arm: dt: hikey: Add optee node
>>   optee: support routing of rpmb data frames to mmc
>>   tee: optee: support AVB trusted application
>>   avb_verify: support using OP-TEE TA AVB
>>
>>  MAINTAINERS                                   |   7 +
>>  arch/arm/dts/hi6220-hikey.dts                 |   7 +
>>  cmd/avb.c                                     |   2 +-
>>  common/avb_verify.c                           | 132 +++-
>>  .../firmware/linaro,optee-tz.txt              |  31 +
>>  drivers/Kconfig                               |   2 +
>>  drivers/Makefile                              |   1 +
>>  drivers/core/root.c                           |  15 +-
>>  drivers/mmc/rpmb.c                            | 160 +++++
>>  drivers/tee/Kconfig                           |  18 +
>>  drivers/tee/Makefile                          |   4 +
>>  drivers/tee/optee/Kconfig                     |  23 +
>>  drivers/tee/optee/Makefile                    |   5 +
>>  drivers/tee/optee/core.c                      | 622 ++++++++++++++++++
>>  drivers/tee/optee/optee_msg.h                 | 423 ++++++++++++
>>  drivers/tee/optee/optee_msg_supplicant.h      | 234 +++++++
>>  drivers/tee/optee/optee_private.h             |  41 ++
>>  drivers/tee/optee/optee_smc.h                 | 444 +++++++++++++
>>  drivers/tee/optee/rpmb.c                      | 184 ++++++
>>  drivers/tee/optee/supplicant.c                |  92 +++
>>  drivers/tee/tee-uclass.c                      | 180 +++++
>>  include/avb_verify.h                          |   4 +
>>  include/dm/uclass-id.h                        |   1 +
>>  include/mmc.h                                 |   2 +
>>  include/tee.h                                 | 141 ++++
>>  include/tee/optee_ta_avb.h                    |  48 ++
>>  26 files changed, 2816 insertions(+), 7 deletions(-)
>>  create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt
>>  create mode 100644 drivers/tee/Kconfig
>>  create mode 100644 drivers/tee/Makefile
>>  create mode 100644 drivers/tee/optee/Kconfig
>>  create mode 100644 drivers/tee/optee/Makefile
>>  create mode 100644 drivers/tee/optee/core.c
>>  create mode 100644 drivers/tee/optee/optee_msg.h
>>  create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
>>  create mode 100644 drivers/tee/optee/optee_private.h
>>  create mode 100644 drivers/tee/optee/optee_smc.h
>>  create mode 100644 drivers/tee/optee/rpmb.c
>>  create mode 100644 drivers/tee/optee/supplicant.c
>>  create mode 100644 drivers/tee/tee-uclass.c
>>  create mode 100644 include/tee.h
>>  create mode 100644 include/tee/optee_ta_avb.h
>>
>> --
>> 2.17.1
>>
>
> I missed the Android Verified Boot stuff going in. I did see the v1
> patch but not the v2.
>
> Was there discussion of coding style for lib/libavb?

I don't know. It was Igor who posted that.

>
> Also, how is this stuff tested in U-Boot? I don't see any tests.

This depends on OP-TEE running in secure world.
The tests are a bit destructive since we're writing in RPMB and also
need to have a specific key programmed.

Before posting the V2 patch set I did some final manual testing:

=> avb init 1
=> avb read_rb 0
I/TC:  Dynamic shared memory is enabled
Rollback index: 0
=> avb read_rb 1
Rollback index: 0
=> avb read_rb 3
Rollback index: 0
=> avb read_rb 4
Rollback index: 0
=> avb read_rb 5
Rollback index: 34
=> avb write_rb 5 3
Failed to write rollback index
=> avb write_rb 5 35
=> avb write_rb 5 3
Failed to write rollback index
=> avb read_rb 5
Rollback index: 35


>
> For the uclass, please add a sandbox driver and test even if there are
> no other tests.

I've added that in the V2 patch set.

Thanks,
Jens

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 00/10] AVB using OP-TEE
  2018-08-23 11:23   ` Jens Wiklander
@ 2018-08-23 12:15     ` Igor Opaniuk
  2018-08-23 16:31     ` Simon Glass
  1 sibling, 0 replies; 40+ messages in thread
From: Igor Opaniuk @ 2018-08-23 12:15 UTC (permalink / raw)
  To: u-boot

Hi Jens,

> Also, how is this stuff tested in U-Boot? I don't see any tests.
I might be wrong, but I guess Simon means U-boot pytests in this context.

When initial AVB2.0 patches were introduced, I've also added some avb
tests for testing functionality rollback indexes/device unlock state
(there were added some simple stubs, so I guess they need to be
extended, to test such cases as updating rb index to the lesser value
etc.)

Please check test/py/tests/test_avb.py for additional details.

BR,
Igor

On 23 August 2018 at 14:23, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Hi Simon,
>
> On Thu, Aug 23, 2018 at 12:45 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Jens,
>>
>> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>>> Hi,
>>>
>>> This adds support for storing AVB rollback indexes in the RPMB partition.
>>> The RPMB partition (content and key) is managed by OP-TEE
>>> (https://www.op-tee.org/) which is a secure OS leveraging ARM TrustZone.
>>>
>>> The Linux kernel can already support OP-TEE with reading and updating
>>> rollback indexes in the RPMB partition, the catch is that this is needed
>>> before the kernel has booted.
>>>
>>> The design here is the same as what is in the Linux kernel, with the
>>> exception that the user space daemon tee-supplicant is integrated in the
>>> OP-TEE driver here (drivers/tee/optee/supplicant.c) instead. A new uclass
>>> (UCLASS_TEE) is introduced to provide an abstraction for interfacing with a
>>> Trusted Execution Environment (TEE). There's also the OP-TEE driver using
>>> UCLASS_TEE for registration.
>>>
>>> A Trusted Application (TA) interface is added to be used by the AVB verify
>>> functions which are updated accordingly. The TA is managed by OP-TEE and is
>>> executed in a secure TrustZone protected environment.
>>>
>>> The header files drivers/tee/optee/optee_{msg,msg_supplicant,smc}.h and
>>> include/tee/optee_ta_avb.h are copied from
>>> https://github.com/OP-TEE/optee_os/tree/master more or less unmodified.
>>> They may need to be updated from time to time in order to support new
>>> features.
>>>
>>> In MMC there's a new function, mmc_rpmb_route_frames(), which as the name
>>> suggests is used to route RPMB frames to/from the MMC. This saves OP-TEE
>>> from implementing an MMC driver which would need to share resources with
>>> its counterpart here in U-boot.
>>>
>>> This was tested on a Hikey (Kirin 620) board.
>>>
>>> I've added myself as maintainer of the TEE stuff.
>>>
>>> Thanks,
>>> Jens
>>>
>>> Jens Wiklander (10):
>>>   dm: fdt: scan for devices under /firmware too
>>>   cmd: avb read_rb: print rb_idx in hexadecimal
>>>   mmc: rpmb: add mmc_rpmb_route_frames()
>>>   Add UCLASS_TEE for Trusted Execution Environment
>>>   dt/bindings: add bindings for optee
>>>   tee: add OP-TEE driver
>>>   arm: dt: hikey: Add optee node
>>>   optee: support routing of rpmb data frames to mmc
>>>   tee: optee: support AVB trusted application
>>>   avb_verify: support using OP-TEE TA AVB
>>>
>>>  MAINTAINERS                                   |   7 +
>>>  arch/arm/dts/hi6220-hikey.dts                 |   7 +
>>>  cmd/avb.c                                     |   2 +-
>>>  common/avb_verify.c                           | 132 +++-
>>>  .../firmware/linaro,optee-tz.txt              |  31 +
>>>  drivers/Kconfig                               |   2 +
>>>  drivers/Makefile                              |   1 +
>>>  drivers/core/root.c                           |  15 +-
>>>  drivers/mmc/rpmb.c                            | 160 +++++
>>>  drivers/tee/Kconfig                           |  18 +
>>>  drivers/tee/Makefile                          |   4 +
>>>  drivers/tee/optee/Kconfig                     |  23 +
>>>  drivers/tee/optee/Makefile                    |   5 +
>>>  drivers/tee/optee/core.c                      | 622 ++++++++++++++++++
>>>  drivers/tee/optee/optee_msg.h                 | 423 ++++++++++++
>>>  drivers/tee/optee/optee_msg_supplicant.h      | 234 +++++++
>>>  drivers/tee/optee/optee_private.h             |  41 ++
>>>  drivers/tee/optee/optee_smc.h                 | 444 +++++++++++++
>>>  drivers/tee/optee/rpmb.c                      | 184 ++++++
>>>  drivers/tee/optee/supplicant.c                |  92 +++
>>>  drivers/tee/tee-uclass.c                      | 180 +++++
>>>  include/avb_verify.h                          |   4 +
>>>  include/dm/uclass-id.h                        |   1 +
>>>  include/mmc.h                                 |   2 +
>>>  include/tee.h                                 | 141 ++++
>>>  include/tee/optee_ta_avb.h                    |  48 ++
>>>  26 files changed, 2816 insertions(+), 7 deletions(-)
>>>  create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt
>>>  create mode 100644 drivers/tee/Kconfig
>>>  create mode 100644 drivers/tee/Makefile
>>>  create mode 100644 drivers/tee/optee/Kconfig
>>>  create mode 100644 drivers/tee/optee/Makefile
>>>  create mode 100644 drivers/tee/optee/core.c
>>>  create mode 100644 drivers/tee/optee/optee_msg.h
>>>  create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
>>>  create mode 100644 drivers/tee/optee/optee_private.h
>>>  create mode 100644 drivers/tee/optee/optee_smc.h
>>>  create mode 100644 drivers/tee/optee/rpmb.c
>>>  create mode 100644 drivers/tee/optee/supplicant.c
>>>  create mode 100644 drivers/tee/tee-uclass.c
>>>  create mode 100644 include/tee.h
>>>  create mode 100644 include/tee/optee_ta_avb.h
>>>
>>> --
>>> 2.17.1
>>>
>>
>> I missed the Android Verified Boot stuff going in. I did see the v1
>> patch but not the v2.
>>
>> Was there discussion of coding style for lib/libavb?
>
> I don't know. It was Igor who posted that.
>
>>
>> Also, how is this stuff tested in U-Boot? I don't see any tests.
>
> This depends on OP-TEE running in secure world.
> The tests are a bit destructive since we're writing in RPMB and also
> need to have a specific key programmed.
>
> Before posting the V2 patch set I did some final manual testing:
>
> => avb init 1
> => avb read_rb 0
> I/TC:  Dynamic shared memory is enabled
> Rollback index: 0
> => avb read_rb 1
> Rollback index: 0
> => avb read_rb 3
> Rollback index: 0
> => avb read_rb 4
> Rollback index: 0
> => avb read_rb 5
> Rollback index: 34
> => avb write_rb 5 3
> Failed to write rollback index
> => avb write_rb 5 35
> => avb write_rb 5 3
> Failed to write rollback index
> => avb read_rb 5
> Rollback index: 35
>
>
>>
>> For the uclass, please add a sandbox driver and test even if there are
>> no other tests.
>
> I've added that in the V2 patch set.
>
> Thanks,
> Jens



-- 
Regards,
Igor Opaniuk

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 00/10] AVB using OP-TEE
  2018-08-23 11:23   ` Jens Wiklander
  2018-08-23 12:15     ` Igor Opaniuk
@ 2018-08-23 16:31     ` Simon Glass
  2018-08-28  6:11       ` Jens Wiklander
  1 sibling, 1 reply; 40+ messages in thread
From: Simon Glass @ 2018-08-23 16:31 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 05:23, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Hi Simon,
>
> On Thu, Aug 23, 2018 at 12:45 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Jens,
>>
>> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>>> Hi,
>>>
>>> This adds support for storing AVB rollback indexes in the RPMB partition.
>>> The RPMB partition (content and key) is managed by OP-TEE
>>> (https://www.op-tee.org/) which is a secure OS leveraging ARM TrustZone.
>>>
>>> The Linux kernel can already support OP-TEE with reading and updating
>>> rollback indexes in the RPMB partition, the catch is that this is needed
>>> before the kernel has booted.
>>>
>>> The design here is the same as what is in the Linux kernel, with the
>>> exception that the user space daemon tee-supplicant is integrated in the
>>> OP-TEE driver here (drivers/tee/optee/supplicant.c) instead. A new uclass
>>> (UCLASS_TEE) is introduced to provide an abstraction for interfacing with a
>>> Trusted Execution Environment (TEE). There's also the OP-TEE driver using
>>> UCLASS_TEE for registration.
>>>
>>> A Trusted Application (TA) interface is added to be used by the AVB verify
>>> functions which are updated accordingly. The TA is managed by OP-TEE and is
>>> executed in a secure TrustZone protected environment.
>>>
>>> The header files drivers/tee/optee/optee_{msg,msg_supplicant,smc}.h and
>>> include/tee/optee_ta_avb.h are copied from
>>> https://github.com/OP-TEE/optee_os/tree/master more or less unmodified.
>>> They may need to be updated from time to time in order to support new
>>> features.
>>>
>>> In MMC there's a new function, mmc_rpmb_route_frames(), which as the name
>>> suggests is used to route RPMB frames to/from the MMC. This saves OP-TEE
>>> from implementing an MMC driver which would need to share resources with
>>> its counterpart here in U-boot.
>>>
>>> This was tested on a Hikey (Kirin 620) board.
>>>
>>> I've added myself as maintainer of the TEE stuff.
>>>
>>> Thanks,
>>> Jens
>>>
>>> Jens Wiklander (10):
>>>   dm: fdt: scan for devices under /firmware too
>>>   cmd: avb read_rb: print rb_idx in hexadecimal
>>>   mmc: rpmb: add mmc_rpmb_route_frames()
>>>   Add UCLASS_TEE for Trusted Execution Environment
>>>   dt/bindings: add bindings for optee
>>>   tee: add OP-TEE driver
>>>   arm: dt: hikey: Add optee node
>>>   optee: support routing of rpmb data frames to mmc
>>>   tee: optee: support AVB trusted application
>>>   avb_verify: support using OP-TEE TA AVB
>>>
>>>  MAINTAINERS                                   |   7 +
>>>  arch/arm/dts/hi6220-hikey.dts                 |   7 +
>>>  cmd/avb.c                                     |   2 +-
>>>  common/avb_verify.c                           | 132 +++-
>>>  .../firmware/linaro,optee-tz.txt              |  31 +
>>>  drivers/Kconfig                               |   2 +
>>>  drivers/Makefile                              |   1 +
>>>  drivers/core/root.c                           |  15 +-
>>>  drivers/mmc/rpmb.c                            | 160 +++++
>>>  drivers/tee/Kconfig                           |  18 +
>>>  drivers/tee/Makefile                          |   4 +
>>>  drivers/tee/optee/Kconfig                     |  23 +
>>>  drivers/tee/optee/Makefile                    |   5 +
>>>  drivers/tee/optee/core.c                      | 622 ++++++++++++++++++
>>>  drivers/tee/optee/optee_msg.h                 | 423 ++++++++++++
>>>  drivers/tee/optee/optee_msg_supplicant.h      | 234 +++++++
>>>  drivers/tee/optee/optee_private.h             |  41 ++
>>>  drivers/tee/optee/optee_smc.h                 | 444 +++++++++++++
>>>  drivers/tee/optee/rpmb.c                      | 184 ++++++
>>>  drivers/tee/optee/supplicant.c                |  92 +++
>>>  drivers/tee/tee-uclass.c                      | 180 +++++
>>>  include/avb_verify.h                          |   4 +
>>>  include/dm/uclass-id.h                        |   1 +
>>>  include/mmc.h                                 |   2 +
>>>  include/tee.h                                 | 141 ++++
>>>  include/tee/optee_ta_avb.h                    |  48 ++
>>>  26 files changed, 2816 insertions(+), 7 deletions(-)
>>>  create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt
>>>  create mode 100644 drivers/tee/Kconfig
>>>  create mode 100644 drivers/tee/Makefile
>>>  create mode 100644 drivers/tee/optee/Kconfig
>>>  create mode 100644 drivers/tee/optee/Makefile
>>>  create mode 100644 drivers/tee/optee/core.c
>>>  create mode 100644 drivers/tee/optee/optee_msg.h
>>>  create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
>>>  create mode 100644 drivers/tee/optee/optee_private.h
>>>  create mode 100644 drivers/tee/optee/optee_smc.h
>>>  create mode 100644 drivers/tee/optee/rpmb.c
>>>  create mode 100644 drivers/tee/optee/supplicant.c
>>>  create mode 100644 drivers/tee/tee-uclass.c
>>>  create mode 100644 include/tee.h
>>>  create mode 100644 include/tee/optee_ta_avb.h
>>>
>>> --
>>> 2.17.1
>>>
>>
>> I missed the Android Verified Boot stuff going in. I did see the v1
>> patch but not the v2.
>>
>> Was there discussion of coding style for lib/libavb?
>
> I don't know. It was Igor who posted that.
>
>>
>> Also, how is this stuff tested in U-Boot? I don't see any tests.
>
> This depends on OP-TEE running in secure world.
> The tests are a bit destructive since we're writing in RPMB and also
> need to have a specific key programmed.
>
> Before posting the V2 patch set I did some final manual testing:
>
> => avb init 1
> => avb read_rb 0
> I/TC:  Dynamic shared memory is enabled
> Rollback index: 0
> => avb read_rb 1
> Rollback index: 0
> => avb read_rb 3
> Rollback index: 0
> => avb read_rb 4
> Rollback index: 0
> => avb read_rb 5
> Rollback index: 34
> => avb write_rb 5 3
> Failed to write rollback index
> => avb write_rb 5 35
> => avb write_rb 5 3
> Failed to write rollback index
> => avb read_rb 5
> Rollback index: 35

OK, I wonder if that can be converted into a simple test in test/py?

Better would be to have a fake sandbox OP-TEE implementation that we
can use to write a test of all the code. Does that sound feasible?

>
>
>>
>> For the uclass, please add a sandbox driver and test even if there are
>> no other tests.
>
> I've added that in the V2 patch set.

OK great.

Regards,
Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-23 11:11     ` Jens Wiklander
@ 2018-08-23 16:31       ` Simon Glass
  0 siblings, 0 replies; 40+ messages in thread
From: Simon Glass @ 2018-08-23 16:31 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 05:11, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Hi Simon,
>
> On Thu, Aug 23, 2018 at 12:45 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Jens,
>>
>> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>>> Adds a uclass to interface with a TEE (Trusted Execution Environment).
>>>
>>> A TEE driver is a driver that interfaces with a trusted OS running in
>>> some secure environment, for example, TrustZone on ARM cpus, or a
>>> separate secure co-processor etc.
>>>
>>> The TEE subsystem can serve a TEE driver for a Global Platform compliant
>>> TEE, but it's not limited to only Global Platform TEEs.
>>>
>>> The over all design is based on the TEE subsystem in the Linux kernel,
>>> tailored for U-boot.
>>>
>>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>>> ---
>>>  MAINTAINERS              |   6 ++
>>>  drivers/Kconfig          |   2 +
>>>  drivers/Makefile         |   1 +
>>>  drivers/tee/Kconfig      |   8 ++
>>>  drivers/tee/Makefile     |   3 +
>>>  drivers/tee/tee-uclass.c | 180 +++++++++++++++++++++++++++++++++++++++
>>>  include/dm/uclass-id.h   |   1 +
>>>  include/tee.h            | 134 +++++++++++++++++++++++++++++
>>>  8 files changed, 335 insertions(+)
>>>  create mode 100644 drivers/tee/Kconfig
>>>  create mode 100644 drivers/tee/Makefile
>>>  create mode 100644 drivers/tee/tee-uclass.c
>>>  create mode 100644 include/tee.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 58b61ac05882..7458c606ee92 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -571,6 +571,12 @@ TQ GROUP
>>>  S:     Orphaned (Since 2016-02)
>>>  T:     git git://git.denx.de/u-boot-tq-group.git
>>>
>>> +TEE
>>> +M:     Jens Wiklander <jens.wiklander@linaro.org>
>>> +S:     Maintained
>>> +F:     drivers/tee/
>>> +F:     include/tee.h
>>> +
>>>  UBI
>>>  M:     Kyungmin Park <kmpark@infradead.org>
>>>  M:     Heiko Schocher <hs@denx.de>
>>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>>> index c72abf893297..f3249ab1d143 100644
>>> --- a/drivers/Kconfig
>>> +++ b/drivers/Kconfig
>>> @@ -94,6 +94,8 @@ source "drivers/spmi/Kconfig"
>>>
>>>  source "drivers/sysreset/Kconfig"
>>>
>>> +source "drivers/tee/Kconfig"
>>> +
>>>  source "drivers/thermal/Kconfig"
>>>
>>>  source "drivers/timer/Kconfig"
>>> diff --git a/drivers/Makefile b/drivers/Makefile
>>> index d53208540ea6..0fcae36f50f7 100644
>>> --- a/drivers/Makefile
>>> +++ b/drivers/Makefile
>>> @@ -103,6 +103,7 @@ obj-y += smem/
>>>  obj-y += soc/
>>>  obj-$(CONFIG_REMOTEPROC) += remoteproc/
>>>  obj-y += thermal/
>>> +obj-$(CONFIG_TEE) += tee/
>>>
>>>  obj-$(CONFIG_MACH_PIC32) += ddr/microchip/
>>>  endif
>>> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
>>> new file mode 100644
>>> index 000000000000..817ab331b0f8
>>> --- /dev/null
>>> +++ b/drivers/tee/Kconfig
>>> @@ -0,0 +1,8 @@
>>> +# Generic Trusted Execution Environment Configuration
>>> +config TEE
>>> +       bool "Trusted Execution Environment support"
>>> +       depends on ARM && (ARM64 || CPU_V7A)
>>> +       select ARM_SMCCC
>>> +       help
>>> +         This implements a generic interface towards a Trusted Execution
>>> +         Environment (TEE).
>>> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
>>> new file mode 100644
>>> index 000000000000..b6d8e16e6211
>>> --- /dev/null
>>> +++ b/drivers/tee/Makefile
>>> @@ -0,0 +1,3 @@
>>> +# SPDX-License-Identifier: GPL-2.0+
>>> +
>>> +obj-y += tee-uclass.o
>>> diff --git a/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
>>> new file mode 100644
>>> index 000000000000..f0243a0f2e4e
>>> --- /dev/null
>>> +++ b/drivers/tee/tee-uclass.c
>>> @@ -0,0 +1,180 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Copyright (c) 2018 Linaro Limited
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <dm.h>
>>> +#include <tee.h>
>>> +
>>> +struct tee_uclass_priv {
>>> +       struct list_head list_shm;
>>> +};
>>> +
>>> +static const struct tee_driver_ops *tee_get_ops(struct udevice *dev)
>>> +{
>>> +       return device_get_ops(dev);
>>> +}
>>> +
>>> +void tee_get_version(struct udevice *dev, struct tee_version_data *vers)
>>> +{
>>> +       tee_get_ops(dev)->get_version(dev, vers);
>>> +}
>>> +
>>> +int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
>>> +                    ulong num_param, struct tee_param *param)
>>> +{
>>> +       return tee_get_ops(dev)->open_session(dev, arg, num_param, param);
>>> +}
>>> +
>>> +int tee_close_session(struct udevice *dev, u32 session)
>>> +{
>>> +       return tee_get_ops(dev)->close_session(dev, session);
>>> +}
>>> +
>>> +int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
>>> +                   ulong num_param, struct tee_param *param)
>>> +{
>>> +       return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
>>> +}
>>> +
>>> +struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
>>> +                             ulong size, u32 flags)
>>> +{
>>> +       struct tee_shm *shm;
>>> +       void *p = addr;
>>> +
>>> +       if (flags & TEE_SHM_ALLOC) {
>>> +               if (align)
>>> +                       p = memalign(align, size);
>>> +               else
>>> +                       p = malloc(size);
>>> +       }
>>> +       if (!p)
>>> +               return NULL;
>>> +
>>> +       shm = calloc(1, sizeof(*shm));
>>> +       if (!shm)
>>> +               goto err;
>>> +
>>> +       shm->dev = dev;
>>> +       shm->addr = p;
>>> +       shm->size = size;
>>> +       shm->flags = flags;
>>> +
>>> +       if ((flags & TEE_SHM_SEC_REGISTER) &&
>>> +           tee_get_ops(dev)->shm_register(dev, shm))
>>> +               goto err;
>>
>> It seems like this can return errors other than -ENOMEM. How about
>> changing this function to return an int?
>
> OK, I'll fix.
>
>>
>>> +
>>> +       if (flags & TEE_SHM_REGISTER) {
>>> +               struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>>> +
>>> +               list_add(&shm->link, &priv->list_shm);
>>> +       }
>>> +       return shm;
>>> +err:
>>> +       free(shm);
>>> +       if (flags & TEE_SHM_ALLOC)
>>> +               free(p);
>>> +       return NULL;
>>> +}
>>> +
>>> +struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size,
>>> +                             u32 flags)
>>> +{
>>> +       u32 f = flags;
>>> +
>>> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
>>
>> blank line before return
>
> OK
>
>>
>>> +       return __tee_shm_add(dev, 0, NULL, size, f);
>>> +}
>>> +
>>> +struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
>>> +                                ulong size, u32 flags)
>>> +{
>>> +       u32 f = flags & ~TEE_SHM_ALLOC;
>>> +
>>> +       f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
>>> +       return __tee_shm_add(dev, 0, addr, size, f);
>>> +}
>>> +
>>> +void tee_shm_free(struct tee_shm *shm)
>>> +{
>>> +       if (!shm)
>>> +               return;
>>> +
>>> +       if (shm->flags & TEE_SHM_SEC_REGISTER)
>>> +               tee_get_ops(shm->dev)->shm_unregister(shm->dev, shm);
>>> +
>>> +       if (shm->flags & TEE_SHM_REGISTER)
>>> +               list_del(&shm->link);
>>> +
>>> +       if (shm->flags & TEE_SHM_ALLOC)
>>> +               free(shm->addr);
>>> +
>>> +       free(shm);
>>> +}
>>> +
>>> +bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev)
>>> +{
>>> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>>> +       struct tee_shm *s;
>>> +
>>> +       list_for_each_entry(s, &priv->list_shm, link)
>>> +               if (s == shm)
>>> +                       return true;
>>> +
>>> +       return false;
>>> +}
>>> +
>>> +struct udevice *tee_find_device(struct udevice *start,
>>> +                               int (*match)(struct tee_version_data *vers,
>>> +                                            const void *data),
>>> +                               const void *data,
>>> +                               struct tee_version_data *vers)
>>> +{
>>> +       struct udevice *dev = start;
>>> +       struct tee_version_data lv;
>>> +       struct tee_version_data *v = vers ? vers : &lv;
>>> +
>>> +       if (!dev)
>>> +               uclass_first_device(UCLASS_TEE, &dev);
>>> +
>>> +       for (; dev; uclass_next_device(&dev)) {
>>> +               tee_get_ops(dev)->get_version(dev, v);
>>> +               if (!match || match(v, data))
>>> +                       return dev;
>>
>> This will probe each device as it looks through them. Is that what you want?
>
> Yes, in practice there will be only one or perhaps in some special
> cases two. The capabilities reported by secure world are needed tee.
>
>>
>>> +       }
>>> +
>>> +       return NULL;
>>> +}
>>> +
>>> +static int tee_pre_probe(struct udevice *dev)
>>> +{
>>> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>>> +
>>> +       INIT_LIST_HEAD(&priv->list_shm);
>>> +       return 0;
>>> +}
>>> +
>>> +static int tee_pre_remove(struct udevice *dev)
>>> +{
>>> +       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
>>> +       struct tee_shm *shm;
>>> +
>>> +       while (!list_empty(&priv->list_shm)) {
>>> +               shm = list_first_entry(&priv->list_shm, struct tee_shm, link);
>>> +               debug("%s: freeing leftover shm %p (size %lu, flags %#x)\n",
>>> +                     __func__, (void *)shm, shm->size, shm->flags);
>>> +               tee_shm_free(shm);
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +UCLASS_DRIVER(tee) = {
>>> +       .id = UCLASS_TEE,
>>> +       .name = "tee",
>>> +       .per_device_auto_alloc_size = sizeof(struct tee_uclass_priv),
>>> +       .pre_probe = tee_pre_probe,
>>> +       .pre_remove = tee_pre_remove,
>>> +};
>>> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
>>> index a39643ec5eef..955e0a915b87 100644
>>> --- a/include/dm/uclass-id.h
>>> +++ b/include/dm/uclass-id.h
>>> @@ -81,6 +81,7 @@ enum uclass_id {
>>>         UCLASS_SPI_GENERIC,     /* Generic SPI flash target */
>>>         UCLASS_SYSCON,          /* System configuration device */
>>>         UCLASS_SYSRESET,        /* System reset device */
>>> +       UCLASS_TEE,             /* Trusted Execution Environment device */
>>
>> We need a bit more information about what this is for. It could go in
>> a README or in the uclass header file.
>>
>>>         UCLASS_THERMAL,         /* Thermal sensor */
>>>         UCLASS_TIMER,           /* Timer device */
>>>         UCLASS_TPM,             /* Trusted Platform Module TIS interface */
>>> diff --git a/include/tee.h b/include/tee.h
>>> new file mode 100644
>>> index 000000000000..c2ac13e34128
>>> --- /dev/null
>>> +++ b/include/tee.h
>>> @@ -0,0 +1,134 @@
>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>> +/*
>>> + * Copyright (c) 2018 Linaro Limited
>>> + */
>>> +
>>> +#ifndef __TEE_H
>>> +#define __TEE_H
>>> +
>>> +#include <common.h>
>>> +#include <dm.h>
>>
>> These should be included by .c files.
>
> Yes, but what those provides is also needed by this .h file.
> Aren't all .h files supposed to include what they depend on?

common.h should be included first by any .c file. I suppose it is not
essential if it does not use CONFIG options (e.g. just a library file
for a 3rd-party library), but that is the general rule. So it should
not be in header files.

For dm.h, I have adopted a similar convention. If you like you can add
things like 'struct udevice;' I have done that in cases where dm.h is
needed. I believe reducing unnecessary includes helps to reduce the
amount of code that goes through the preprocessor, but perhaps I am
superstitious. Chrome C++ does the same thing.

> Thanks for the review. I posted V2 of this patch set at the same time
> as you replied, I'll address what's not already done in V2 in the
> coming V3.

Yes I think I lost an email as I thought I had already replied on some
of these points, and apparently I had.

Regards,
Simon

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [U-Boot] [PATCH 00/10] AVB using OP-TEE
  2018-08-23 16:31     ` Simon Glass
@ 2018-08-28  6:11       ` Jens Wiklander
  0 siblings, 0 replies; 40+ messages in thread
From: Jens Wiklander @ 2018-08-28  6:11 UTC (permalink / raw)
  To: u-boot

On Thu, Aug 23, 2018 at 6:31 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Jens,
>
> On 23 August 2018 at 05:23, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> Hi Simon,
>>
>> On Thu, Aug 23, 2018 at 12:45 PM, Simon Glass <sjg@chromium.org> wrote:
>>> Hi Jens,
>>>
>>> On 13 August 2018 at 09:53, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>>>> Hi,
>>>>
>>>> This adds support for storing AVB rollback indexes in the RPMB partition.
>>>> The RPMB partition (content and key) is managed by OP-TEE
>>>> (https://www.op-tee.org/) which is a secure OS leveraging ARM TrustZone.
>>>>
>>>> The Linux kernel can already support OP-TEE with reading and updating
>>>> rollback indexes in the RPMB partition, the catch is that this is needed
>>>> before the kernel has booted.
>>>>
>>>> The design here is the same as what is in the Linux kernel, with the
>>>> exception that the user space daemon tee-supplicant is integrated in the
>>>> OP-TEE driver here (drivers/tee/optee/supplicant.c) instead. A new uclass
>>>> (UCLASS_TEE) is introduced to provide an abstraction for interfacing with a
>>>> Trusted Execution Environment (TEE). There's also the OP-TEE driver using
>>>> UCLASS_TEE for registration.
>>>>
>>>> A Trusted Application (TA) interface is added to be used by the AVB verify
>>>> functions which are updated accordingly. The TA is managed by OP-TEE and is
>>>> executed in a secure TrustZone protected environment.
>>>>
>>>> The header files drivers/tee/optee/optee_{msg,msg_supplicant,smc}.h and
>>>> include/tee/optee_ta_avb.h are copied from
>>>> https://github.com/OP-TEE/optee_os/tree/master more or less unmodified.
>>>> They may need to be updated from time to time in order to support new
>>>> features.
>>>>
>>>> In MMC there's a new function, mmc_rpmb_route_frames(), which as the name
>>>> suggests is used to route RPMB frames to/from the MMC. This saves OP-TEE
>>>> from implementing an MMC driver which would need to share resources with
>>>> its counterpart here in U-boot.
>>>>
>>>> This was tested on a Hikey (Kirin 620) board.
>>>>
>>>> I've added myself as maintainer of the TEE stuff.
>>>>
>>>> Thanks,
>>>> Jens
>>>>
>>>> Jens Wiklander (10):
>>>>   dm: fdt: scan for devices under /firmware too
>>>>   cmd: avb read_rb: print rb_idx in hexadecimal
>>>>   mmc: rpmb: add mmc_rpmb_route_frames()
>>>>   Add UCLASS_TEE for Trusted Execution Environment
>>>>   dt/bindings: add bindings for optee
>>>>   tee: add OP-TEE driver
>>>>   arm: dt: hikey: Add optee node
>>>>   optee: support routing of rpmb data frames to mmc
>>>>   tee: optee: support AVB trusted application
>>>>   avb_verify: support using OP-TEE TA AVB
>>>>
>>>>  MAINTAINERS                                   |   7 +
>>>>  arch/arm/dts/hi6220-hikey.dts                 |   7 +
>>>>  cmd/avb.c                                     |   2 +-
>>>>  common/avb_verify.c                           | 132 +++-
>>>>  .../firmware/linaro,optee-tz.txt              |  31 +
>>>>  drivers/Kconfig                               |   2 +
>>>>  drivers/Makefile                              |   1 +
>>>>  drivers/core/root.c                           |  15 +-
>>>>  drivers/mmc/rpmb.c                            | 160 +++++
>>>>  drivers/tee/Kconfig                           |  18 +
>>>>  drivers/tee/Makefile                          |   4 +
>>>>  drivers/tee/optee/Kconfig                     |  23 +
>>>>  drivers/tee/optee/Makefile                    |   5 +
>>>>  drivers/tee/optee/core.c                      | 622 ++++++++++++++++++
>>>>  drivers/tee/optee/optee_msg.h                 | 423 ++++++++++++
>>>>  drivers/tee/optee/optee_msg_supplicant.h      | 234 +++++++
>>>>  drivers/tee/optee/optee_private.h             |  41 ++
>>>>  drivers/tee/optee/optee_smc.h                 | 444 +++++++++++++
>>>>  drivers/tee/optee/rpmb.c                      | 184 ++++++
>>>>  drivers/tee/optee/supplicant.c                |  92 +++
>>>>  drivers/tee/tee-uclass.c                      | 180 +++++
>>>>  include/avb_verify.h                          |   4 +
>>>>  include/dm/uclass-id.h                        |   1 +
>>>>  include/mmc.h                                 |   2 +
>>>>  include/tee.h                                 | 141 ++++
>>>>  include/tee/optee_ta_avb.h                    |  48 ++
>>>>  26 files changed, 2816 insertions(+), 7 deletions(-)
>>>>  create mode 100644 doc/device-tree-bindings/firmware/linaro,optee-tz.txt
>>>>  create mode 100644 drivers/tee/Kconfig
>>>>  create mode 100644 drivers/tee/Makefile
>>>>  create mode 100644 drivers/tee/optee/Kconfig
>>>>  create mode 100644 drivers/tee/optee/Makefile
>>>>  create mode 100644 drivers/tee/optee/core.c
>>>>  create mode 100644 drivers/tee/optee/optee_msg.h
>>>>  create mode 100644 drivers/tee/optee/optee_msg_supplicant.h
>>>>  create mode 100644 drivers/tee/optee/optee_private.h
>>>>  create mode 100644 drivers/tee/optee/optee_smc.h
>>>>  create mode 100644 drivers/tee/optee/rpmb.c
>>>>  create mode 100644 drivers/tee/optee/supplicant.c
>>>>  create mode 100644 drivers/tee/tee-uclass.c
>>>>  create mode 100644 include/tee.h
>>>>  create mode 100644 include/tee/optee_ta_avb.h
>>>>
>>>> --
>>>> 2.17.1
>>>>
>>>
>>> I missed the Android Verified Boot stuff going in. I did see the v1
>>> patch but not the v2.
>>>
>>> Was there discussion of coding style for lib/libavb?
>>
>> I don't know. It was Igor who posted that.
>>
>>>
>>> Also, how is this stuff tested in U-Boot? I don't see any tests.
>>
>> This depends on OP-TEE running in secure world.
>> The tests are a bit destructive since we're writing in RPMB and also
>> need to have a specific key programmed.
>>
>> Before posting the V2 patch set I did some final manual testing:
>>
>> => avb init 1
>> => avb read_rb 0
>> I/TC:  Dynamic shared memory is enabled
>> Rollback index: 0
>> => avb read_rb 1
>> Rollback index: 0
>> => avb read_rb 3
>> Rollback index: 0
>> => avb read_rb 4
>> Rollback index: 0
>> => avb read_rb 5
>> Rollback index: 34
>> => avb write_rb 5 3
>> Failed to write rollback index
>> => avb write_rb 5 35
>> => avb write_rb 5 3
>> Failed to write rollback index
>> => avb read_rb 5
>> Rollback index: 35
>
> OK, I wonder if that can be converted into a simple test in test/py?
>
> Better would be to have a fake sandbox OP-TEE implementation that we
> can use to write a test of all the code. Does that sound feasible?

Good idea, shouldn't be too hard.

Thanks,
Jens

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2018-08-28  6:11 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-13 15:53 [U-Boot] [PATCH 00/10] AVB using OP-TEE Jens Wiklander
2018-08-13 15:53 ` [U-Boot] [PATCH 01/10] dm: fdt: scan for devices under /firmware too Jens Wiklander
2018-08-15 14:17   ` Tom Rini
2018-08-15 14:30     ` Michal Simek
2018-08-15 14:34       ` Tom Rini
2018-08-15 14:50         ` Michal Simek
2018-08-15 14:50           ` Michal Simek
2018-08-15 15:31           ` [U-Boot] " Rob Herring
2018-08-15 15:31             ` Rob Herring
2018-08-15 15:43             ` [U-Boot] " Tom Rini
2018-08-15 15:43               ` Tom Rini
2018-08-13 15:53 ` [U-Boot] [PATCH 02/10] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
2018-08-14 11:34   ` Igor Opaniuk
2018-08-13 15:53 ` [U-Boot] [PATCH 03/10] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
2018-08-16 12:13   ` Igor Opaniuk
2018-08-22 13:52     ` Jens Wiklander
2018-08-13 15:53 ` [U-Boot] [PATCH 04/10] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
2018-08-16 12:14   ` Igor Opaniuk
2018-08-17 12:48   ` Simon Glass
2018-08-21  9:20     ` Jens Wiklander
2018-08-23 10:45   ` Simon Glass
2018-08-23 11:11     ` Jens Wiklander
2018-08-23 16:31       ` Simon Glass
2018-08-13 15:53 ` [U-Boot] [PATCH 05/10] dt/bindings: add bindings for optee Jens Wiklander
2018-08-13 15:53 ` [U-Boot] [PATCH 06/10] tee: add OP-TEE driver Jens Wiklander
2018-08-16 12:17   ` Igor Opaniuk
2018-08-13 15:53 ` [U-Boot] [PATCH 07/10] arm: dt: hikey: Add optee node Jens Wiklander
2018-08-13 15:53 ` [U-Boot] [PATCH 08/10] optee: support routing of rpmb data frames to mmc Jens Wiklander
2018-08-16 12:23   ` Igor Opaniuk
2018-08-13 15:53 ` [U-Boot] [PATCH 09/10] tee: optee: support AVB trusted application Jens Wiklander
2018-08-16 12:22   ` Igor Opaniuk
2018-08-19 12:42     ` Igor Opaniuk
2018-08-13 15:53 ` [U-Boot] [PATCH 10/10] avb_verify: support using OP-TEE TA AVB Jens Wiklander
2018-08-14 11:20   ` Igor Opaniuk
2018-08-16 12:17     ` Igor Opaniuk
2018-08-23 10:45 ` [U-Boot] [PATCH 00/10] AVB using OP-TEE Simon Glass
2018-08-23 11:23   ` Jens Wiklander
2018-08-23 12:15     ` Igor Opaniuk
2018-08-23 16:31     ` Simon Glass
2018-08-28  6:11       ` Jens Wiklander

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.