All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 00/15] AVB using OP-TEE
@ 2018-08-23 10:43 Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too Jens Wiklander
                   ` (14 more replies)
  0 siblings, 15 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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.

v2:
* Added sandbox driver and a test in test/dm for the new TEE uclass:
  Commit ("test: tee: test TEE uclass") and the enabling commits
  ("sandbox: dt: add sandbox_tee node") and
  ("configs: sandbox: enable CONFIG_TEE (TEE uclass)")
* Added descriptions of exported structs and functions
* Added documentation for the TEE uclass and the OP-TEE driver with
  the new commit ("Documentation: tee uclass and op-tee driver")
* Added documentation for the changes in avb_verify
* Addressed review comments from Simon Glass
* Added the commit ("cmd: avb: print error message if command fails")
* Made a few functions static in the OP-TEE driver
* Commit ("cmd: avb read_rb: print rb_idx in hexadecimal") and
  ("tee: optee: support AVB trusted application");
  Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>

Thanks,
Jens

Jens Wiklander (15):
  dm: fdt: scan for devices under /firmware too
  cmd: avb read_rb: print rb_idx in hexadecimal
  cmd: avb: print error message if command fails
  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
  Documentation: tee uclass and op-tee driver
  test: tee: test TEE uclass
  sandbox: dt: add sandbox_tee node
  configs: sandbox: enable CONFIG_TEE (TEE uclass)
  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 +
 arch/sandbox/dts/sandbox.dts                  |   4 +
 arch/sandbox/dts/sandbox64.dts                |   4 +
 arch/sandbox/dts/test.dts                     |   4 +
 cmd/avb.c                                     |  19 +-
 common/avb_verify.c                           | 132 +++-
 configs/sandbox64_defconfig                   |   1 +
 configs/sandbox_defconfig                     |   1 +
 configs/sandbox_flattree_defconfig            |   1 +
 configs/sandbox_noblk_defconfig               |   1 +
 configs/sandbox_spl_defconfig                 |   1 +
 doc/README.avb2                               |  13 +
 doc/README.tee                                | 112 ++++
 .../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                           |  17 +
 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                      | 192 ++++++
 include/avb_verify.h                          |   4 +
 include/dm/uclass-id.h                        |   1 +
 include/mmc.h                                 |   2 +
 include/tee.h                                 | 297 +++++++++
 include/tee/optee_ta_avb.h                    |  48 ++
 test/dm/Makefile                              |   1 +
 test/dm/tee.c                                 | 182 +++++
 38 files changed, 3325 insertions(+), 7 deletions(-)
 create mode 100644 doc/README.tee
 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
 create mode 100644 test/dm/tee.c

-- 
2.17.1

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

* [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2020-01-07  8:49   ` Michal Simek
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 02/15] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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] 38+ messages in thread

* [U-Boot] [PATCH v2 02/15] cmd: avb read_rb: print rb_idx in hexadecimal
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 03/15] cmd: avb: print error message if command fails Jens Wiklander
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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 hexadecimal number too.

Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>
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] 38+ messages in thread

* [U-Boot] [PATCH v2 03/15] cmd: avb: print error message if command fails
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 02/15] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 04/15] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 UTC (permalink / raw)
  To: u-boot

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

diff --git a/cmd/avb.c b/cmd/avb.c
index ca4b26d5d7b3..ff00be4cee38 100644
--- a/cmd/avb.c
+++ b/cmd/avb.c
@@ -35,6 +35,8 @@ int do_avb_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	if (avb_ops)
 		return CMD_RET_SUCCESS;
 
+	printf("Failed to initialize avb2\n");
+
 	return CMD_RET_FAILURE;
 }
 
@@ -65,6 +67,8 @@ int do_avb_read_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return CMD_RET_SUCCESS;
 	}
 
+	printf("Failed to read from partition\n");
+
 	return CMD_RET_FAILURE;
 }
 
@@ -108,6 +112,8 @@ int do_avb_read_part_hex(cmd_tbl_t *cmdtp, int flag, int argc,
 		return CMD_RET_SUCCESS;
 	}
 
+	printf("Failed to read from partition\n");
+
 	free(buffer);
 	return CMD_RET_FAILURE;
 }
@@ -138,6 +144,8 @@ int do_avb_write_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		return CMD_RET_SUCCESS;
 	}
 
+	printf("Failed to write in partition\n");
+
 	return CMD_RET_FAILURE;
 }
 
@@ -161,6 +169,9 @@ int do_avb_read_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		printf("Rollback index: %llx\n", rb_idx);
 		return CMD_RET_SUCCESS;
 	}
+
+	printf("Failed to read rollback index\n");
+
 	return CMD_RET_FAILURE;
 }
 
@@ -184,6 +195,8 @@ int do_avb_write_rb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	    AVB_IO_RESULT_OK)
 		return CMD_RET_SUCCESS;
 
+	printf("Failed to write rollback index\n");
+
 	return CMD_RET_FAILURE;
 }
 
@@ -210,6 +223,8 @@ int do_avb_get_uuid(cmd_tbl_t *cmdtp, int flag,
 		return CMD_RET_SUCCESS;
 	}
 
+	printf("Failed to read UUID\n");
+
 	return CMD_RET_FAILURE;
 }
 
@@ -320,6 +335,8 @@ int do_avb_is_unlocked(cmd_tbl_t *cmdtp, int flag,
 		return CMD_RET_SUCCESS;
 	}
 
+	printf("Can't determine device lock state.\n");
+
 	return CMD_RET_FAILURE;
 }
 
-- 
2.17.1

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

* [U-Boot] [PATCH v2 04/15] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (2 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 03/15] cmd: avb: print error message if command fails Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 UTC (permalink / raw)
  To: u-boot

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

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
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] 38+ messages in thread

* [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (3 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 04/15] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 06/15] dt/bindings: add bindings for optee Jens Wiklander
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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.

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
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 | 192 ++++++++++++++++++++++++++
 include/dm/uclass-id.h   |   1 +
 include/tee.h            | 290 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 503 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..0209983491a0
--- /dev/null
+++ b/drivers/tee/tee-uclass.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <tee.h>
+
+/**
+ * struct tee_uclass_priv - information of a TEE, stored by the uclass
+ *
+ * @list_shm:	list of structe tee_shm representing memory blocks shared
+ *		with the TEE.
+ */
+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;
+
+	/*
+	 * Any remaining shared memory must be unregistered now as U-boot
+	 * is about to hand over to the next stage and that memory will be
+	 * reused.
+	 */
+	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..3e6771123ef0
--- /dev/null
+++ b/include/tee.h
@@ -0,0 +1,290 @@
+/* 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)	/* In list of shared memory */
+#define TEE_SHM_SEC_REGISTER	BIT(1)	/* TEE notified of this memory */
+#define TEE_SHM_ALLOC		BIT(2)	/* The memory is malloced() and must */
+					/* be freed() */
+
+#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 in
+ * struct tee_version_data::gen_caps
+ */
+#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_shm - memory shared with the TEE
+ * @dev:	The TEE device
+ * @link:	List node in the list in struct struct tee_uclass_priv
+ * @addr:	Pointer to the shared memory
+ * @size:	Size of the the shared memory
+ * @flags:	TEE_SHM_* above
+ */
+struct tee_shm {
+	struct udevice *dev;
+	struct list_head link;
+	void *addr;
+	ulong size;
+	u32 flags;
+};
+
+/**
+ * struct tee_param_memref - parameter memory reference
+ * @shm_offs:	Offset in bytes into the shared memory object @shm
+ * @size:	Size in bytes of the memory reference
+ * @shm:	Pointer to a shared memory object for the buffer
+ */
+struct tee_param_memref {
+	ulong shm_offs;
+	ulong size;
+	struct tee_shm *shm;
+};
+
+/**
+ * struct tee_param_value - value parameter
+ * @a, @b, @c:	Parameters passed by value
+ */
+struct tee_param_value {
+	u64 a;
+	u64 b;
+	u64 c;
+};
+
+/**
+ * struct tee_param - invoke parameter
+ * @attr:	Attributes
+ * @u.memref:	Memref parameter if (@attr & TEE_PARAM_ATTR_MASK) is one of
+ *		TEE_PARAM_ATTR_TYPE_MEMREF_* above
+ * @u.value:	Value parameter if (@attr & TEE_PARAM_ATTR_MASK) is one of
+ *		TEE_PARAM_ATTR_TYPE_VALUE_* above
+ */
+struct tee_param {
+	u64 attr;
+	union {
+		struct tee_param_memref memref;
+		struct tee_param_value value;
+	} u;
+};
+
+/**
+ * struct tee_open_session_arg - extra arguments for tee_open_session()
+ * @uuid:	[in] UUID of the Trusted Application
+ * @clnt_uuid:	[in] Normally zeroes
+ * @clnt_login:	[in] Normally 0
+ * @session:	[out] Session id
+ * @ret:	[out] return value
+ * @ret_origin:	[out] origin of the return value
+ */
+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 - extra arguments for tee_invoke_func()
+ * @func:	[in] Trusted Application function, specific to the TA
+ * @session:	[in] Session id, from open session
+ * @ret:	[out] return value
+ * @ret_origin:	[out] origin of the return value
+ */
+struct tee_invoke_arg {
+	u32 func;
+	u32 session;
+	u32 ret;
+	u32 ret_origin;
+};
+
+/**
+ * struct tee_version_data - description of TEE
+ * @gen_caps:	Generic capabilities, TEE_GEN_CAP_* above
+ */
+struct tee_version_data {
+	u32 gen_caps;
+};
+
+/**
+ * struct tee_driver_ops - TEE driver operations
+ * @get_version:	Query capabilities of TEE device,
+			see tee_get_version()
+ * @open_session:	Opens a session to a Trusted Application in the TEE,
+ *			see tee_open_session().
+ * @close_session:	Closes a session to Trusted Application,
+ *			see tee_close_session()
+ * @invoke_func:	Invokes a function in a Trusted Application,
+			see tee_invoke_func()
+ */
+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);
+	/**
+	 * shm_register() - Registers memory shared with the TEE
+	 * @dev:	The TEE device
+	 * @shm:	Pointer to a shared memory object
+	 * Returns 0 on success or < 0 on failure.
+	 */
+	int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
+	/**
+	 * shm_unregister() - Unregisters memory shared with the TEE
+	 * @dev:	The TEE device
+	 * @shm:	Pointer to a shared memory object
+	 * Returns 0 on success or < 0 on failure.
+	 */
+	int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
+};
+
+/**
+ * __tee_shm_add() - Internal helper function to register shared memory
+ * @dev:	The TEE device
+ * @align:	Required alignment of allocated memory block if
+ *		(@flags & TEE_SHM_ALLOC)
+ * @addr:	Address of memory block, ignored if (@flags & TEE_SHM_ALLOC)
+ * @size:	Size of memory block
+ * @flags:	TEE_SHM_* above
+ *
+ * returns pointer to struct tee_shm on success or NULL on error
+ */
+struct tee_shm *__tee_shm_add(struct udevice *dev, ulong align, void *addr,
+			      ulong size, u32 flags);
+
+/**
+ * tee_shm_alloc() - Allocate shared memory
+ * @dev:	The TEE device
+ * @size:	Size of memory block
+ * @flags:	TEE_SHM_* above
+ *
+ * returns pointer to struct tee_shm on success or NULL on error
+ */
+struct tee_shm *tee_shm_alloc(struct udevice *dev, ulong size, u32 flags);
+
+/**
+ * tee_shm_register() - Registers shared memory
+ * @dev:	The TEE device
+ * @addr:	Address of memory block
+ * @size:	Size of memory block
+ * @flags:	TEE_SHM_* above
+ *
+ * returns pointer to struct tee_shm on success or NULL on error
+ */
+struct tee_shm *tee_shm_register(struct udevice *dev, void *addr,
+				 ulong length, u32 flags);
+
+/**
+ * tee_shm_free() - Frees shared memory
+ * @shm:	Shared memory object
+ */
+void tee_shm_free(struct tee_shm *shm);
+
+/**
+ * tee_shm_is_registered() - Check register status of shared memory object
+ * @shm:	Pointer to shared memory object
+ * @dev:	The TEE device
+ *
+ * Returns true if the shared memory object is registered for the supplied
+ * TEE device
+ */
+bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev);
+
+/**
+ * tee_find_device() - Look up a TEE device
+ * @start:	if not NULL, continue search after this device
+ * @match:	function to check TEE device
+ * @data:	data for match function
+ * @vers:	if not NULL, version data of TEE device of the device returned
+ *
+ * Returns a probed TEE device of the first TEE device matched by the
+ * match() callback or NULL.
+ */
+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);
+
+/**
+ * tee_get_version() - Query capabilities of TEE device
+ * @dev:	The TEE device
+ * @vers:	Pointer to version data
+ */
+void tee_get_version(struct udevice *dev, struct tee_version_data *vers);
+
+/**
+ * tee_open_session() - Open a session to a Trusted Application
+ * @dev:	The TEE device
+ * @arg:	Open session arguments
+ * @num_param:	Number of elements in @param
+ * @param:	Parameters for Trusted Application
+ *
+ * Returns < 0 on error else see @arg->ret for result. If @arg->ret is
+ * TEE_SUCCESS the session identifier is available in @arg->session.
+ */
+int tee_open_session(struct udevice *dev, struct tee_open_session_arg *arg,
+		     ulong num_param, struct tee_param *param);
+
+/**
+ * tee_close_session() - Close a session to a Trusted Application
+ * @dev:	The TEE device
+ * @session:	Session id
+ *
+ * Return < 0 on error else 0, regardless the session will not be valid
+ * after this function has returned.
+ */
+int tee_close_session(struct udevice *dev, u32 session);
+
+/**
+ * tee_invoke_func() - Invoke a function in a Trusted Application
+ * @dev:	The TEE device
+ * @arg:	Invoke arguments
+ * @num_param:	Number of elements in @param
+ * @param:	Parameters for Trusted Application
+ *
+ * Returns < 0 on error else see @arg->ret for result.
+ */
+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] 38+ messages in thread

* [U-Boot] [PATCH v2 06/15] dt/bindings: add bindings for optee
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (4 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver Jens Wiklander
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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] 38+ messages in thread

* [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (5 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 06/15] dt/bindings: add bindings for optee Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver Jens Wiklander
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
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..f2d92d96551b
--- /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;
+}
+
+static 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);
+		}
+	}
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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] 38+ messages in thread

* [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (6 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 09/15] test: tee: test TEE uclass Jens Wiklander
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 doc/README.tee | 112 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 112 insertions(+)
 create mode 100644 doc/README.tee

diff --git a/doc/README.tee b/doc/README.tee
new file mode 100644
index 000000000000..e9c9ef67877a
--- /dev/null
+++ b/doc/README.tee
@@ -0,0 +1,112 @@
+=============
+TEE uclass
+=============
+
+This document describes the TEE uclass in U-boot
+
+A TEE (Trusted Execution Environment) is a trusted OS running in some
+secure environment, for example, TrustZone on ARM CPUs, or a separate
+secure co-processor etc. A TEE driver handles the details needed to
+communicate with the TEE.
+
+This uclass deals with:
+
+- Registration of TEE drivers
+
+- Managing shared memory between U-boot and the TEE
+
+- Providing a generic API to the TEE
+
+The TEE interface
+=================
+
+include/tee.h defines the generic interface to a TEE.
+
+A client finds the TEE device via tee_find_device(). Other important functions
+when interfacing with a TEE are:
+
+- tee_shm_alloc(), tee_shm_register() and tee_shm_free() to manage shared
+  memory objects often needed when communicating with the TEE.
+
+- tee_get_version() lets the client know which the capabilities of the TEE
+  device.
+
+- tee_open_session() opens a session to a Trusted Application
+
+- tee_invoke_func() invokes a function in a Trusted Application
+
+- tee_close_session() closes a session to a Trusted Application
+
+Much of the communication between clients and the TEE is opaque to the
+driver. The main job for the driver is to receive requests from the
+clients, forward them to the TEE and send back the results.
+
+OP-TEE driver
+=============
+
+The OP-TEE driver handles OP-TEE [1] based TEEs. Currently it is only the ARM
+TrustZone based OP-TEE solution that is supported.
+
+Lowest level of communication with OP-TEE builds on ARM SMC Calling
+Convention (SMCCC) [2], which is the foundation for OP-TEE's SMC interface
+[3] used internally by the driver. Stacked on top of that is OP-TEE Message
+Protocol [4].
+
+OP-TEE SMC interface provides the basic functions required by SMCCC and some
+additional functions specific for OP-TEE. The most interesting functions are:
+
+- OPTEE_SMC_FUNCID_CALLS_UID (part of SMCCC) returns the version information
+  which is then returned by TEE_IOC_VERSION
+
+- OPTEE_SMC_CALL_GET_OS_UUID returns the particular OP-TEE implementation, used
+  to tell, for instance, a TrustZone OP-TEE apart from an OP-TEE running on a
+  separate secure co-processor.
+
+- OPTEE_SMC_CALL_WITH_ARG drives the OP-TEE message protocol
+
+- OPTEE_SMC_GET_SHM_CONFIG lets the driver and OP-TEE agree on which memory
+  range to used for shared memory between Linux and OP-TEE.
+
+The GlobalPlatform TEE Client API [5] is implemented on top of the generic
+TEE API.
+
+Picture of the relationship between the different components in the
+OP-TEE architecture:
+
+                   U-boot                  Secure world
+                   ~~~~~~                  ~~~~~~~~~~~~
+                 +------------+           +-------------+
+                 | Client     |           | Trusted     |
+                 |            |           | Application |
+                 +------------+           +-------------+
+                       /\                       /\
+                       ||                       ||
+                       \/                       \/
+                 +------------+           +-------------+
+                 | TEE        |           | TEE Internal|
+                 | uclass     |           | API         |
+                 +------------+           +-------------+
+                 | OP-TEE     |           | OP-TEE      |
+                 | driver     |           | Trusted OS  |
+                 +------------+-----------+-------------+
+                 |             OP-TEE MSG               |
+                 |      SMCCC (OPTEE_SMC_CALL_*)        |
+                 +--------------------------------------+
+
+RPC (Remote Procedure Call) are requests from secure world to the driver.
+An RPC is identified by a special range of SMCCC return values from
+OPTEE_SMC_CALL_WITH_ARG.
+
+References
+==========
+
+[1] https://github.com/OP-TEE/optee_os
+
+[2] http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+
+[3] drivers/tee/optee/optee_smc.h
+
+[4] drivers/tee/optee/optee_msg.h
+
+[5] http://www.globalplatform.org/specificationsdevice.asp look for
+    "TEE Client API Specification v1.0" and click download.
-- 
2.17.1

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

* [U-Boot] [PATCH v2 09/15] test: tee: test TEE uclass
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (7 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node Jens Wiklander
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 UTC (permalink / raw)
  To: u-boot

Tests the TEE uclass with a sandbox tee driver.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 drivers/tee/Kconfig |   5 +-
 test/dm/Makefile    |   1 +
 test/dm/tee.c       | 182 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+), 3 deletions(-)
 create mode 100644 test/dm/tee.c

diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
index 3e7fe6ddcc5d..032aff4777c6 100644
--- a/drivers/tee/Kconfig
+++ b/drivers/tee/Kconfig
@@ -1,8 +1,8 @@
 # Generic Trusted Execution Environment Configuration
 config TEE
 	bool "Trusted Execution Environment support"
-	depends on ARM && (ARM64 || CPU_V7A)
-	select ARM_SMCCC
+	depends on (ARM && (ARM64 || CPU_V7A)) || SANDBOX
+	select ARM_SMCCC if ARM
 	help
 	  This implements a generic interface towards a Trusted Execution
 	  Environment (TEE).
@@ -14,5 +14,4 @@ menu "TEE drivers"
 source "drivers/tee/optee/Kconfig"
 
 endmenu
-
 endif
diff --git a/test/dm/Makefile b/test/dm/Makefile
index d2ed96c61533..272374b92fb0 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -44,4 +44,5 @@ obj-$(CONFIG_DM_VIDEO) += video.o
 obj-$(CONFIG_ADC) += adc.o
 obj-$(CONFIG_SPMI) += spmi.o
 obj-$(CONFIG_WDT) += wdt.o
+obj-$(CONFIG_TEE) += tee.o
 endif
diff --git a/test/dm/tee.c b/test/dm/tee.c
new file mode 100644
index 000000000000..bf9db0c130ac
--- /dev/null
+++ b/test/dm/tee.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <tee.h>
+#include <test/ut.h>
+
+struct sandbox_tee_state {
+	u32 session;
+	int num_shms;
+};
+
+static void sandbox_tee_get_version(struct udevice *dev,
+				    struct tee_version_data *vers)
+{
+	memset(vers, 0, sizeof(*vers));
+}
+
+static int sandbox_tee_close_session(struct udevice *dev, u32 session)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+
+	if (!state->session || state->session != session)
+		return -EINVAL;
+
+	state->session = 0;
+
+	return 0;
+}
+
+static int sandbox_tee_open_session(struct udevice *dev,
+				    struct tee_open_session_arg *arg,
+				    ulong num_params, struct tee_param *params)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+
+	if (state->session)
+		return -EBUSY;
+
+	state->session = 1;
+	arg->session = state->session;
+
+	return 0;
+}
+
+static int sandbox_tee_invoke_func(struct udevice *dev,
+				   struct tee_invoke_arg *arg,
+				   ulong num_params, struct tee_param *params)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+
+	if (!arg->session)
+		return -EINVAL;
+
+	if (arg->session != state->session)
+		return -EINVAL;
+
+	if (arg->func != 1)
+		return -ENOENT;
+
+	return 0;
+}
+
+static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+
+	state->num_shms++;
+
+	return 0;
+}
+
+static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+
+	state->num_shms--;
+
+	return 0;
+}
+
+static const struct tee_driver_ops sandbox_tee_ops = {
+	.get_version = sandbox_tee_get_version,
+	.open_session = sandbox_tee_open_session,
+	.close_session = sandbox_tee_close_session,
+	.invoke_func = sandbox_tee_invoke_func,
+	.shm_register = sandbox_tee_shm_register,
+	.shm_unregister = sandbox_tee_shm_unregister,
+};
+
+static const struct udevice_id sandbox_tee_match[] = {
+	{ .compatible = "sandbox,tee" },
+	{},
+};
+
+U_BOOT_DRIVER(sandbox_tee) = {
+	.name = "sandbox_tee",
+	.id = UCLASS_TEE,
+	.of_match = sandbox_tee_match,
+	.ops = &sandbox_tee_ops,
+	.priv_auto_alloc_size = sizeof(struct sandbox_tee_state),
+};
+
+static int open_session(struct udevice *dev, u32 *session)
+{
+	struct tee_open_session_arg arg;
+	int rc;
+
+	memset(&arg, 0, sizeof(arg));
+	rc = tee_open_session(dev, &arg, 0, NULL);
+	if (rc)
+		return rc;
+	if (arg.ret)
+		return -EIO;
+	*session = arg.session;
+
+	return 0;
+}
+
+static int invoke_func(struct udevice *dev, u32 session, u32 func)
+{
+	struct tee_invoke_arg arg = { .session = session, .func = func };
+
+	return tee_invoke_func(dev, &arg, 0, NULL);
+}
+
+static int match(struct tee_version_data *vers, const void *data)
+{
+	return !vers->gen_caps;
+}
+
+static int dm_test_tee(struct unit_test_state *uts)
+{
+	struct tee_version_data vers;
+	struct udevice *dev;
+	struct sandbox_tee_state *state;
+	u32 session;
+	int rc;
+	u8 data[128];
+	struct tee_shm *reg_shm;
+	struct tee_shm *alloc_shm;
+
+	dev = tee_find_device(NULL, match, NULL, &vers);
+	ut_assert(dev);
+	state = dev_get_priv(dev);
+	ut_assert(!state->session);
+
+	rc = open_session(dev, &session);
+	ut_assert(!rc);
+	ut_assert(session == state->session);
+
+	rc = invoke_func(dev, session, 1);
+	ut_assert(!rc);
+
+	rc = tee_close_session(dev, session);
+	ut_assert(!rc);
+	ut_assert(!state->session);
+
+	ut_assert(!state->num_shms);
+	reg_shm = tee_shm_register(dev, data, sizeof(data), 0);
+	ut_assert(reg_shm);
+	ut_assert(state->num_shms == 1);
+
+	alloc_shm = tee_shm_alloc(dev, 256, 0);
+	ut_assert(alloc_shm);
+	ut_assert(state->num_shms == 2);
+
+	ut_assert(tee_shm_is_registered(reg_shm, dev));
+	ut_assert(tee_shm_is_registered(alloc_shm, dev));
+
+	tee_shm_free(reg_shm);
+	tee_shm_free(alloc_shm);
+	ut_assert(!state->num_shms);
+
+	return 0;
+}
+
+DM_TEST(dm_test_tee, DM_TESTF_SCAN_FDT);
-- 
2.17.1

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

* [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (8 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 09/15] test: tee: test TEE uclass Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass) Jens Wiklander
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 UTC (permalink / raw)
  To: u-boot

Adds a sandbox_tee node to enable the sandbox tee driver in all the
sandbox dts files.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/sandbox/dts/sandbox.dts   | 4 ++++
 arch/sandbox/dts/sandbox64.dts | 4 ++++
 arch/sandbox/dts/test.dts      | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9f444c96a9ec..f5c02e5396ff 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -311,6 +311,10 @@
 			};
 		};
 	};
+
+	sandbox_tee {
+		compatible = "sandbox,tee";
+	};
 };
 
 #include "cros-ec-keyboard.dtsi"
diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts
index 9e65d2fda3d3..0e32fdad9d81 100644
--- a/arch/sandbox/dts/sandbox64.dts
+++ b/arch/sandbox/dts/sandbox64.dts
@@ -311,6 +311,10 @@
 			};
 		};
 	};
+
+	sandbox_tee {
+		compatible = "sandbox,tee";
+	};
 };
 
 #include "cros-ec-keyboard.dtsi"
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 70356461959d..eee7518be823 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -604,6 +604,10 @@
 			};
 		};
 	};
+
+	sandbox_tee {
+		compatible = "sandbox,tee";
+	};
 };
 
 #include "sandbox_pmic.dtsi"
-- 
2.17.1

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

* [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass)
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (9 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:29   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 12/15] arm: dt: hikey: Add optee node Jens Wiklander
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 configs/sandbox64_defconfig        | 1 +
 configs/sandbox_defconfig          | 1 +
 configs/sandbox_flattree_defconfig | 1 +
 configs/sandbox_noblk_defconfig    | 1 +
 configs/sandbox_spl_defconfig      | 1 +
 5 files changed, 5 insertions(+)

diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 5bd5927b410b..213755589382 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -199,3 +199,4 @@ CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
 CONFIG_UT_OVERLAY=y
+CONFIG_TEE=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index afc34298ed9f..e9cba7895c33 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -200,3 +200,4 @@ CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
 CONFIG_UT_OVERLAY=y
+CONFIG_TEE=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 84b0756a4dc7..80f3055fd079 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -174,3 +174,4 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_TEE=y
diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig
index d1ca61bff2e8..54ba5bc7dd36 100644
--- a/configs/sandbox_noblk_defconfig
+++ b/configs/sandbox_noblk_defconfig
@@ -175,3 +175,4 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_TEE=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index c00672f6cc0d..87cbd67c6d21 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -194,3 +194,4 @@ CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
 CONFIG_UT_ENV=y
+CONFIG_TEE=y
-- 
2.17.1

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

* [U-Boot] [PATCH v2 12/15] arm: dt: hikey: Add optee node
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (10 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass) Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:29   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc Jens Wiklander
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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] 38+ messages in thread

* [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (11 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 12/15] arm: dt: hikey: Add optee node Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:29   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application Jens Wiklander
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 15/15] avb_verify: support using OP-TEE TA AVB Jens Wiklander
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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.

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
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 f2d92d96551b..e297d206af3a 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] 38+ messages in thread

* [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (12 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  2018-08-30  0:29   ` Simon Glass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 15/15] avb_verify: support using OP-TEE TA AVB Jens Wiklander
  14 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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.

Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>
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 3e6771123ef0..b851d718d32f 100644
--- a/include/tee.h
+++ b/include/tee.h
@@ -48,6 +48,13 @@
 
 #define TEE_ORIGIN_COMMS		0x00000002
 
+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 - memory shared with the TEE
  * @dev:	The TEE device
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] 38+ messages in thread

* [U-Boot] [PATCH v2 15/15] avb_verify: support using OP-TEE TA AVB
  2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
                   ` (13 preceding siblings ...)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application Jens Wiklander
@ 2018-08-23 10:43 ` Jens Wiklander
  14 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-23 10:43 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 ++++++++++++++++++++++++++++++++++++++++++-
 doc/README.avb2      |  13 +++++
 include/avb_verify.h |   4 ++
 3 files changed, 148 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/doc/README.avb2 b/doc/README.avb2
index 120279fedbe2..a29cee1b6f50 100644
--- a/doc/README.avb2
+++ b/doc/README.avb2
@@ -18,6 +18,13 @@ Integrity of the bootloader (U-boot BLOB and environment) is out of scope.
 For additional details check:
 https://android.googlesource.com/platform/external/avb/+/master/README.md
 
+1.1. AVB using OP-TEE (optional)
+---------------------------------
+If AVB is configured to use OP-TEE (see 4. below) rollback indexes and
+device lock state are stored in RPMB. The RPMB partition is managed by
+OP-TEE (https://www.op-tee.org/) which is a secure OS leveraging ARM
+TrustZone.
+
 
 2. AVB 2.0 U-BOOT SHELL COMMANDS
 -----------------------------------
@@ -61,6 +68,12 @@ CONFIG_LIBAVB=y
 CONFIG_AVB_VERIFY=y
 CONFIG_CMD_AVB=y
 
+In addtion optionally if storing rollback indexes in RPMB with help of
+OP-TEE:
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_OPTEE_TA_AVB=y
+CONFIG_SUPPORT_EMMC_RPMB=y
 
 Then add `avb verify` invocation to your android boot sequence of commands,
 e.g.:
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] 38+ messages in thread

* [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  2020-01-07  8:49   ` Michal Simek
  1 sibling, 0 replies; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> 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(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v2 02/15] cmd: avb read_rb: print rb_idx in hexadecimal
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 02/15] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  0 siblings, 0 replies; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, 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 hexadecimal number too.
>
> Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  cmd/avb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v2 03/15] cmd: avb: print error message if command fails
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 03/15] cmd: avb: print error message if command fails Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  0 siblings, 0 replies; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  cmd/avb.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  2018-08-30 13:16     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 04:43, 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.

U-Boot

>
> Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> 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 | 192 ++++++++++++++++++++++++++
>  include/dm/uclass-id.h   |   1 +
>  include/tee.h            | 290 +++++++++++++++++++++++++++++++++++++++
>  8 files changed, 503 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

Reviewed-by: Simon Glass <sjg@chromium.org>

Various nits below.

>
> 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).

Please expand this. What is it? Why would I use it? Also perhaps add a web link?

> 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..0209983491a0
> --- /dev/null
> +++ b/drivers/tee/tee-uclass.c
> @@ -0,0 +1,192 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <tee.h>
> +
> +/**
> + * struct tee_uclass_priv - information of a TEE, stored by the uclass
> + *
> + * @list_shm:  list of structe tee_shm representing memory blocks shared
> + *             with the TEE.
> + */
> +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;

blank line here

> +       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;

and here

> +       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)

Please add function comment

> +{
> +       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);

This can return an error if it finds a device but it tails to probe.
If you don't care about that, I suppose it is OK.

> +
> +       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;
> +
> +       /*
> +        * Any remaining shared memory must be unregistered now as U-boot

U-Boot

> +        * is about to hand over to the next stage and that memory will be
> +        * reused.
> +        */
> +       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..3e6771123ef0
> --- /dev/null
> +++ b/include/tee.h
> @@ -0,0 +1,290 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2018 Linaro Limited
> + */
> +
> +#ifndef __TEE_H
> +#define __TEE_H
> +
> +#include <common.h>
> +#include <dm.h>

Please drop both of those.

> +
> +#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)  /* In list of shared memory */
> +#define TEE_SHM_SEC_REGISTER   BIT(1)  /* TEE notified of this memory */
> +#define TEE_SHM_ALLOC          BIT(2)  /* The memory is malloced() and must */
> +                                       /* be freed() */
> +
> +#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 in
> + * struct tee_version_data::gen_caps
> + */
> +#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_shm - memory shared with the TEE
> + * @dev:       The TEE device
> + * @link:      List node in the list in struct struct tee_uclass_priv
> + * @addr:      Pointer to the shared memory
> + * @size:      Size of the the shared memory
> + * @flags:     TEE_SHM_* above
> + */
> +struct tee_shm {
> +       struct udevice *dev;
> +       struct list_head link;
> +       void *addr;
> +       ulong size;
> +       u32 flags;
> +};
> +
> +/**
> + * struct tee_param_memref - parameter memory reference

Used for ...?

> + * @shm_offs:  Offset in bytes into the shared memory object @shm
> + * @size:      Size in bytes of the memory reference
> + * @shm:       Pointer to a shared memory object for the buffer
> + */
> +struct tee_param_memref {
> +       ulong shm_offs;
> +       ulong size;
> +       struct tee_shm *shm;
> +};
> +
> +/**
> + * struct tee_param_value - value parameter

??

This doesn't really explain anything. What is it for?

> + * @a, @b, @c: Parameters passed by value
> + */
> +struct tee_param_value {
> +       u64 a;
> +       u64 b;
> +       u64 c;
> +};
> +
> +/**
> + * struct tee_param - invoke parameter
> + * @attr:      Attributes
> + * @u.memref:  Memref parameter if (@attr & TEE_PARAM_ATTR_MASK) is one of
> + *             TEE_PARAM_ATTR_TYPE_MEMREF_* above
> + * @u.value:   Value parameter if (@attr & TEE_PARAM_ATTR_MASK) is one of
> + *             TEE_PARAM_ATTR_TYPE_VALUE_* above
> + */
> +struct tee_param {
> +       u64 attr;
> +       union {
> +               struct tee_param_memref memref;
> +               struct tee_param_value value;
> +       } u;
> +};
> +
> +/**
> + * struct tee_open_session_arg - extra arguments for tee_open_session()
> + * @uuid:      [in] UUID of the Trusted Application
> + * @clnt_uuid: [in] Normally zeroes
> + * @clnt_login:        [in] Normally 0
> + * @session:   [out] Session id
> + * @ret:       [out] return value
> + * @ret_origin:        [out] origin of the return value
> + */
> +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;

Do these use the sized u32 type because it is an API of some sort?
Otherwise, why not uint?

> +};
> +
> +/**
> + * struct tee_invoke_arg - extra arguments for tee_invoke_func()
> + * @func:      [in] Trusted Application function, specific to the TA
> + * @session:   [in] Session id, from open session
> + * @ret:       [out] return value
> + * @ret_origin:        [out] origin of the return value
> + */
> +struct tee_invoke_arg {
> +       u32 func;
> +       u32 session;
> +       u32 ret;
> +       u32 ret_origin;
> +};
> +
> +/**
> + * struct tee_version_data - description of TEE
> + * @gen_caps:  Generic capabilities, TEE_GEN_CAP_* above
> + */
> +struct tee_version_data {
> +       u32 gen_caps;
> +};
> +
> +/**
> + * struct tee_driver_ops - TEE driver operations
> + * @get_version:       Query capabilities of TEE device,
> +                       see tee_get_version()
> + * @open_session:      Opens a session to a Trusted Application in the TEE,
> + *                     see tee_open_session().
> + * @close_session:     Closes a session to Trusted Application,
> + *                     see tee_close_session()
> + * @invoke_func:       Invokes a function in a Trusted Application,
> +                       see tee_invoke_func()

These comments should be against each function in the struct below.
You should repeat the comment from the exported functions there too.

> + */
> +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);
> +       /**
> +        * shm_register() - Registers memory shared with the TEE
> +        * @dev:        The TEE device
> +        * @shm:        Pointer to a shared memory object
> +        * Returns 0 on success or < 0 on failure.
> +        */
> +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
> +       /**
> +        * shm_unregister() - Unregisters memory shared with the TEE
> +        * @dev:        The TEE device
> +        * @shm:        Pointer to a shared memory object
> +        * Returns 0 on success or < 0 on failure.
> +        */
> +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
> +};
> +
[...]

Regards,
Simon

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

* [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  2018-08-31  7:02     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 04:43, 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

U-Boot

Please use this consistent.

> * Probes OP-TEE version using SMCs
> * Uses OPTEE message protocol version 2 to communicate with secure world
>
> Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> 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
>

Reviewed-by: Simon Glass <sjg@chromium.org>

> 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.

for ARM? I think you should expand this help. What does the driver support / do?

> 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..f2d92d96551b
> --- /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>

Put linux/ ones after 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);

Can you not remove the u64 here?

E.g.

(void *)((ulong)reg0 << 32) | reg1)

> +}
> +
> +static void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)

Function comment

> +{
> +       *reg0 = val >> 32;
> +       *reg1 = val;
> +}
> +
> +void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr)

Function comment

> +{
> +       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));

Drop extra pair of ()

> +       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;
> +}
> +
> +static int to_msg_param(struct optee_msg_param *msg_params, ulong num_params,
> +                       const struct tee_param *params)
> +{
> +       ulong n;

uint? int?

Save below

> +
> +       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);
> +               }
> +       }
> +}
> +
> +static 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);

blank line before return

> +       return 0;
> +}
> +

[..]

> 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.

Does this file have an upstream, or is this specific to U-Boot? If the
former, please add a reference.

> + *
> + * 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.
> + */
> +

[...]

Regards,
Simon

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

* [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  2018-08-31  8:04     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  doc/README.tee | 112 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 112 insertions(+)
>  create mode 100644 doc/README.tee

Reviewed-by: Simon Glass <sjg@chromium.org>

Looks good, nits below.


>
> diff --git a/doc/README.tee b/doc/README.tee
> new file mode 100644
> index 000000000000..e9c9ef67877a
> --- /dev/null
> +++ b/doc/README.tee
> @@ -0,0 +1,112 @@
> +=============
> +TEE uclass
> +=============
> +
> +This document describes the TEE uclass in U-boot

U-Boot

(please can you check all your patches for that? There are more below)

> +
> +A TEE (Trusted Execution Environment) is a trusted OS running in some
> +secure environment, for example, TrustZone on ARM CPUs, or a separate
> +secure co-processor etc. A TEE driver handles the details needed to
> +communicate with the TEE.
> +
> +This uclass deals with:
> +
> +- Registration of TEE drivers
> +
> +- Managing shared memory between U-boot and the TEE
> +
> +- Providing a generic API to the TEE
> +
> +The TEE interface
> +=================
> +
> +include/tee.h defines the generic interface to a TEE.
> +
> +A client finds the TEE device via tee_find_device(). Other important functions
> +when interfacing with a TEE are:
> +
> +- tee_shm_alloc(), tee_shm_register() and tee_shm_free() to manage shared
> +  memory objects often needed when communicating with the TEE.
> +
> +- tee_get_version() lets the client know which the capabilities of the TEE
> +  device.
> +
> +- tee_open_session() opens a session to a Trusted Application
> +
> +- tee_invoke_func() invokes a function in a Trusted Application
> +
> +- tee_close_session() closes a session to a Trusted Application
> +
> +Much of the communication between clients and the TEE is opaque to the
> +driver. The main job for the driver is to receive requests from the
> +clients, forward them to the TEE and send back the results.
> +
> +OP-TEE driver
> +=============
> +
> +The OP-TEE driver handles OP-TEE [1] based TEEs. Currently it is only the ARM
> +TrustZone based OP-TEE solution that is supported.

In fact, wouldn't other things be supported by different drivers?

Perhaps you should name your driver to indicate it is only for ARM?

> +
> +Lowest level of communication with OP-TEE builds on ARM SMC Calling
> +Convention (SMCCC) [2], which is the foundation for OP-TEE's SMC interface
> +[3] used internally by the driver. Stacked on top of that is OP-TEE Message
> +Protocol [4].
> +
> +OP-TEE SMC interface provides the basic functions required by SMCCC and some
> +additional functions specific for OP-TEE. The most interesting functions are:
> +
> +- OPTEE_SMC_FUNCID_CALLS_UID (part of SMCCC) returns the version information
> +  which is then returned by TEE_IOC_VERSION
> +
> +- OPTEE_SMC_CALL_GET_OS_UUID returns the particular OP-TEE implementation, used
> +  to tell, for instance, a TrustZone OP-TEE apart from an OP-TEE running on a
> +  separate secure co-processor.
> +
> +- OPTEE_SMC_CALL_WITH_ARG drives the OP-TEE message protocol
> +
> +- OPTEE_SMC_GET_SHM_CONFIG lets the driver and OP-TEE agree on which memory
> +  range to used for shared memory between Linux and OP-TEE.
> +
> +The GlobalPlatform TEE Client API [5] is implemented on top of the generic
> +TEE API.
> +
> +Picture of the relationship between the different components in the
> +OP-TEE architecture:
> +
> +                   U-boot                  Secure world
> +                   ~~~~~~                  ~~~~~~~~~~~~
> +                 +------------+           +-------------+
> +                 | Client     |           | Trusted     |
> +                 |            |           | Application |
> +                 +------------+           +-------------+
> +                       /\                       /\
> +                       ||                       ||
> +                       \/                       \/
> +                 +------------+           +-------------+
> +                 | TEE        |           | TEE Internal|
> +                 | uclass     |           | API         |
> +                 +------------+           +-------------+
> +                 | OP-TEE     |           | OP-TEE      |
> +                 | driver     |           | Trusted OS  |
> +                 +------------+-----------+-------------+
> +                 |             OP-TEE MSG               |
> +                 |      SMCCC (OPTEE_SMC_CALL_*)        |
> +                 +--------------------------------------+
> +
> +RPC (Remote Procedure Call) are requests from secure world to the driver.
> +An RPC is identified by a special range of SMCCC return values from
> +OPTEE_SMC_CALL_WITH_ARG.
> +
> +References
> +==========
> +
> +[1] https://github.com/OP-TEE/optee_os
> +
> +[2] http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
> +
> +[3] drivers/tee/optee/optee_smc.h
> +
> +[4] drivers/tee/optee/optee_msg.h
> +
> +[5] http://www.globalplatform.org/specificationsdevice.asp look for
> +    "TEE Client API Specification v1.0" and click download.
> --
> 2.17.1
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 09/15] test: tee: test TEE uclass
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 09/15] test: tee: test TEE uclass Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  0 siblings, 0 replies; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Tests the TEE uclass with a sandbox tee driver.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  drivers/tee/Kconfig |   5 +-
>  test/dm/Makefile    |   1 +
>  test/dm/tee.c       | 182 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 185 insertions(+), 3 deletions(-)
>  create mode 100644 test/dm/tee.c

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node Jens Wiklander
@ 2018-08-30  0:28   ` Simon Glass
  2018-08-31  8:06     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:28 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds a sandbox_tee node to enable the sandbox tee driver in all the
> sandbox dts files.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  arch/sandbox/dts/sandbox.dts   | 4 ++++
>  arch/sandbox/dts/sandbox64.dts | 4 ++++
>  arch/sandbox/dts/test.dts      | 4 ++++
>  3 files changed, 12 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

BTW it's only the test.dts one that matters for tests. But it's fine
to add this in the others.

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

* [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass)
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass) Jens Wiklander
@ 2018-08-30  0:29   ` Simon Glass
  2018-08-31  8:08     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:29 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  configs/sandbox64_defconfig        | 1 +
>  configs/sandbox_defconfig          | 1 +
>  configs/sandbox_flattree_defconfig | 1 +
>  configs/sandbox_noblk_defconfig    | 1 +
>  configs/sandbox_spl_defconfig      | 1 +
>  5 files changed, 5 insertions(+)
>

Can you move this to an 'imply' in arch/Kconfig?

Regards,
Simon

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

* [U-Boot] [PATCH v2 12/15] arm: dt: hikey: Add optee node
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 12/15] arm: dt: hikey: Add optee node Jens Wiklander
@ 2018-08-30  0:29   ` Simon Glass
  0 siblings, 0 replies; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:29 UTC (permalink / raw)
  To: u-boot

On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> 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(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application Jens Wiklander
@ 2018-08-30  0:29   ` Simon Glass
  2018-08-31 12:10     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:29 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 04:43, 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.

What is AVB? Can you please write it out in full?

>
> Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> 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 3e6771123ef0..b851d718d32f 100644
> --- a/include/tee.h
> +++ b/include/tee.h
> @@ -48,6 +48,13 @@
>
>  #define TEE_ORIGIN_COMMS               0x00000002
>
> +struct tee_optee_ta_uuid {

Comment on this struct. What is it for?

> +       u32 time_low;
> +       u16 time_mid;
> +       u16 time_hi_and_version;
> +       u8 clock_seq_and_node[8];
> +};
> +
>  /**
>   * struct tee_shm - memory shared with the TEE
>   * @dev:       The TEE device
> 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*/

Space before */

> --
> 2.17.1
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc Jens Wiklander
@ 2018-08-30  0:29   ` Simon Glass
  2018-08-30 14:41     ` Jens Wiklander
  0 siblings, 1 reply; 38+ messages in thread
From: Simon Glass @ 2018-08-30  0:29 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 23 August 2018 at 04:43, 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.
>
> Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> 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 f2d92d96551b..e297d206af3a 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 {

doc comment

> +       struct mmc *rpmb_mmc;
> +       int rpmb_dev_id;
> +       char rpmb_original_part;

Why is this char? Are you trying to save memory? I doubt it will work :-)


> +};
> +
> +struct optee_msg_arg;
> +
> +void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
> +                    void **page_list);

Function comments.

> +
> +#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

You shouldn't support !CONFIG_BLK. It is going away in the next release.

> +       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,
Simon

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

* [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment
  2018-08-30  0:28   ` Simon Glass
@ 2018-08-30 13:16     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-30 13:16 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 29, 2018 at 06:28:48PM -0600, Simon Glass wrote:
> Hi Jens,
> 
> On 23 August 2018 at 04:43, 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.
> 
> U-Boot
> 
> >
> > Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> > 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 | 192 ++++++++++++++++++++++++++
> >  include/dm/uclass-id.h   |   1 +
> >  include/tee.h            | 290 +++++++++++++++++++++++++++++++++++++++
> >  8 files changed, 503 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
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> Various nits below.
> 
> >
> > 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).
> 
> Please expand this. What is it? Why would I use it? Also perhaps add a
> web link?

I'll expand it. I'll skip the why part though.

> 
> > 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..0209983491a0
> > --- /dev/null
> > +++ b/drivers/tee/tee-uclass.c
> > @@ -0,0 +1,192 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2018 Linaro Limited
> > + */
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <tee.h>
> > +
> > +/**
> > + * struct tee_uclass_priv - information of a TEE, stored by the uclass
> > + *
> > + * @list_shm:  list of structe tee_shm representing memory blocks shared
> > + *             with the TEE.
> > + */
> > +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;
> 
> blank line here
> 
> > +       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;
> 
> and here
> 
> > +       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)
> 
> Please add function comment

There is one in include/tee.h

> > +{
> > +       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);
> 
> This can return an error if it finds a device but it tails to probe.
> If you don't care about that, I suppose it is OK.

Thanks. I need the first device that probes OK and then the next devices
that probes OK and so on. I'll need to make some small changes here.

> > +
> > +       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;
> > +
> > +       /*
> > +        * Any remaining shared memory must be unregistered now as U-boot
> 
> U-Boot
> 
> > +        * is about to hand over to the next stage and that memory will be
> > +        * reused.
> > +        */
> > +       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..3e6771123ef0
> > --- /dev/null
> > +++ b/include/tee.h
> > @@ -0,0 +1,290 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2018 Linaro Limited
> > + */
> > +
> > +#ifndef __TEE_H
> > +#define __TEE_H
> > +
> > +#include <common.h>
> > +#include <dm.h>
> 
> Please drop both of those.
> 
> > +
> > +#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)  /* In list of shared memory */
> > +#define TEE_SHM_SEC_REGISTER   BIT(1)  /* TEE notified of this memory */
> > +#define TEE_SHM_ALLOC          BIT(2)  /* The memory is malloced() and must */
> > +                                       /* be freed() */
> > +
> > +#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 in
> > + * struct tee_version_data::gen_caps
> > + */
> > +#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_shm - memory shared with the TEE
> > + * @dev:       The TEE device
> > + * @link:      List node in the list in struct struct tee_uclass_priv
> > + * @addr:      Pointer to the shared memory
> > + * @size:      Size of the the shared memory
> > + * @flags:     TEE_SHM_* above
> > + */
> > +struct tee_shm {
> > +       struct udevice *dev;
> > +       struct list_head link;
> > +       void *addr;
> > +       ulong size;
> > +       u32 flags;
> > +};
> > +
> > +/**
> > + * struct tee_param_memref - parameter memory reference
> 
> Used for ...?
> 
> > + * @shm_offs:  Offset in bytes into the shared memory object @shm
> > + * @size:      Size in bytes of the memory reference
> > + * @shm:       Pointer to a shared memory object for the buffer
> > + */
> > +struct tee_param_memref {
> > +       ulong shm_offs;
> > +       ulong size;
> > +       struct tee_shm *shm;
> > +};
> > +
> > +/**
> > + * struct tee_param_value - value parameter
> 
> ??
> 
> This doesn't really explain anything. What is it for?

I'll expand and refer to struct tee_param below.

> 
> > + * @a, @b, @c: Parameters passed by value
> > + */
> > +struct tee_param_value {
> > +       u64 a;
> > +       u64 b;
> > +       u64 c;
> > +};
> > +
> > +/**
> > + * struct tee_param - invoke parameter
> > + * @attr:      Attributes
> > + * @u.memref:  Memref parameter if (@attr & TEE_PARAM_ATTR_MASK) is one of
> > + *             TEE_PARAM_ATTR_TYPE_MEMREF_* above
> > + * @u.value:   Value parameter if (@attr & TEE_PARAM_ATTR_MASK) is one of
> > + *             TEE_PARAM_ATTR_TYPE_VALUE_* above
> > + */
> > +struct tee_param {
> > +       u64 attr;
> > +       union {
> > +               struct tee_param_memref memref;
> > +               struct tee_param_value value;
> > +       } u;
> > +};
> > +
> > +/**
> > + * struct tee_open_session_arg - extra arguments for tee_open_session()
> > + * @uuid:      [in] UUID of the Trusted Application
> > + * @clnt_uuid: [in] Normally zeroes
> > + * @clnt_login:        [in] Normally 0
> > + * @session:   [out] Session id
> > + * @ret:       [out] return value
> > + * @ret_origin:        [out] origin of the return value
> > + */
> > +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;
> 
> Do these use the sized u32 type because it is an API of some sort?
> Otherwise, why not uint?

Yes, the minimum width is 32-bits and wider than that is waste.

> 
> > +};
> > +
> > +/**
> > + * struct tee_invoke_arg - extra arguments for tee_invoke_func()
> > + * @func:      [in] Trusted Application function, specific to the TA
> > + * @session:   [in] Session id, from open session
> > + * @ret:       [out] return value
> > + * @ret_origin:        [out] origin of the return value
> > + */
> > +struct tee_invoke_arg {
> > +       u32 func;
> > +       u32 session;
> > +       u32 ret;
> > +       u32 ret_origin;
> > +};
> > +
> > +/**
> > + * struct tee_version_data - description of TEE
> > + * @gen_caps:  Generic capabilities, TEE_GEN_CAP_* above
> > + */
> > +struct tee_version_data {
> > +       u32 gen_caps;
> > +};
> > +
> > +/**
> > + * struct tee_driver_ops - TEE driver operations
> > + * @get_version:       Query capabilities of TEE device,
> > +                       see tee_get_version()
> > + * @open_session:      Opens a session to a Trusted Application in the TEE,
> > + *                     see tee_open_session().
> > + * @close_session:     Closes a session to Trusted Application,
> > + *                     see tee_close_session()
> > + * @invoke_func:       Invokes a function in a Trusted Application,
> > +                       see tee_invoke_func()
> 
> These comments should be against each function in the struct below.
> You should repeat the comment from the exported functions there too.

I'll fix.

> 
> > + */
> > +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);
> > +       /**
> > +        * shm_register() - Registers memory shared with the TEE
> > +        * @dev:        The TEE device
> > +        * @shm:        Pointer to a shared memory object
> > +        * Returns 0 on success or < 0 on failure.
> > +        */
> > +       int (*shm_register)(struct udevice *dev, struct tee_shm *shm);
> > +       /**
> > +        * shm_unregister() - Unregisters memory shared with the TEE
> > +        * @dev:        The TEE device
> > +        * @shm:        Pointer to a shared memory object
> > +        * Returns 0 on success or < 0 on failure.
> > +        */
> > +       int (*shm_unregister)(struct udevice *dev, struct tee_shm *shm);
> > +};
> > +
> [...]

Thanks for the review.
--
Jens

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

* [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc
  2018-08-30  0:29   ` Simon Glass
@ 2018-08-30 14:41     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-30 14:41 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Aug 29, 2018 at 06:29:12PM -0600, Simon Glass wrote:
> Hi Jens,
> 
> On 23 August 2018 at 04:43, 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.
> >
> > Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> > 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 f2d92d96551b..e297d206af3a 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 {
> 
> doc comment

OK, I'll fix.

> 
> > +       struct mmc *rpmb_mmc;
> > +       int rpmb_dev_id;
> > +       char rpmb_original_part;
> 
> Why is this char? Are you trying to save memory? I doubt it will work :-)

Good question. I think I got it from struct blk_desc::hwpart, but still
got it slightly wrong. I'll change it into an int instead.

> 
> 
> > +};
> > +
> > +struct optee_msg_arg;
> > +
> > +void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
> > +                    void **page_list);
> 
> Function comments.
> 
> > +
> > +#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
> 
> You shouldn't support !CONFIG_BLK. It is going away in the next release.

OK, I'll remove the ifdef and just keep the
mmc_get_blk_desc(mmc)->hwpart line then.

> 
> > +       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
> >

Thanks for the review,
Jens

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

* [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver
  2018-08-30  0:28   ` Simon Glass
@ 2018-08-31  7:02     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-31  7:02 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 29, 2018 at 06:28:51PM -0600, Simon Glass wrote:
> Hi Jens,
> 
> On 23 August 2018 at 04:43, 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
> 
> U-Boot
> 
> Please use this consistent.

Sorry, it seems I've found lots of ways of doing that wrong.

> 
> > * Probes OP-TEE version using SMCs
> > * Uses OPTEE message protocol version 2 to communicate with secure world
> >
> > Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> > 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
> >
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> > 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.
> 
> for ARM? I think you should expand this help. What does the driver
> support / do?

I'll expand this.

> > 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..f2d92d96551b
> > --- /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>
> 
> Put linux/ ones after tee.h

OK

> > +
> > +#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);
> 
> Can you not remove the u64 here?
> 
> E.g.
> 
> (void *)((ulong)reg0 << 32) | reg1)

No, that will cause:
drivers/tee/optee/core.c:42:38: warning: left shift count >= width of type [-Wshift-count-overflow]
  return (void *)(ulong)(((ulong)reg0 << 32) | reg1);
                                      ^~
on ILP32

> 
> > +}
> > +
> > +static void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
> 
> Function comment
> 
> > +{
> > +       *reg0 = val >> 32;
> > +       *reg1 = val;
> > +}
> > +
> > +void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr)
> 
> Function comment
> 
> > +{
> > +       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));
> 
> Drop extra pair of ()
> 
> > +       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;
> > +}
> > +
> > +static int to_msg_param(struct optee_msg_param *msg_params, ulong num_params,
> > +                       const struct tee_param *params)
> > +{
> > +       ulong n;
> 
> uint? int?
> 
> Save below

OK, I'll change the type for holding number of parameters to uint
here and everywhere else.

> 
> > +
> > +       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);
> > +               }
> > +       }
> > +}
> > +
> > +static 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);
> 
> blank line before return
> 
> > +       return 0;
> > +}
> > +
> 
> [..]
> 
> > 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.
> 
> Does this file have an upstream, or is this specific to U-Boot? If the
> former, please add a reference.

Yes, there's an upstream. I'll update.

> 
> > + *
> > + * 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.
> > + */
> > +
> 
> [...]

Thanks for the review,
Jens

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

* [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver
  2018-08-30  0:28   ` Simon Glass
@ 2018-08-31  8:04     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-31  8:04 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Aug 29, 2018 at 06:28:54PM -0600, Simon Glass wrote:
> Hi Jens,
> 
> On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> > Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  doc/README.tee | 112 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 112 insertions(+)
> >  create mode 100644 doc/README.tee
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> Looks good, nits below.
> 
> 
> >
> > diff --git a/doc/README.tee b/doc/README.tee
> > new file mode 100644
> > index 000000000000..e9c9ef67877a
> > --- /dev/null
> > +++ b/doc/README.tee
> > @@ -0,0 +1,112 @@
> > +=============
> > +TEE uclass
> > +=============
> > +
> > +This document describes the TEE uclass in U-boot
> 
> U-Boot
> 
> (please can you check all your patches for that? There are more below)

Yes, I'll check them all.

> 
> > +
> > +A TEE (Trusted Execution Environment) is a trusted OS running in some
> > +secure environment, for example, TrustZone on ARM CPUs, or a separate
> > +secure co-processor etc. A TEE driver handles the details needed to
> > +communicate with the TEE.
> > +
> > +This uclass deals with:
> > +
> > +- Registration of TEE drivers
> > +
> > +- Managing shared memory between U-boot and the TEE
> > +
> > +- Providing a generic API to the TEE
> > +
> > +The TEE interface
> > +=================
> > +
> > +include/tee.h defines the generic interface to a TEE.
> > +
> > +A client finds the TEE device via tee_find_device(). Other important functions
> > +when interfacing with a TEE are:
> > +
> > +- tee_shm_alloc(), tee_shm_register() and tee_shm_free() to manage shared
> > +  memory objects often needed when communicating with the TEE.
> > +
> > +- tee_get_version() lets the client know which the capabilities of the TEE
> > +  device.
> > +
> > +- tee_open_session() opens a session to a Trusted Application
> > +
> > +- tee_invoke_func() invokes a function in a Trusted Application
> > +
> > +- tee_close_session() closes a session to a Trusted Application
> > +
> > +Much of the communication between clients and the TEE is opaque to the
> > +driver. The main job for the driver is to receive requests from the
> > +clients, forward them to the TEE and send back the results.
> > +
> > +OP-TEE driver
> > +=============
> > +
> > +The OP-TEE driver handles OP-TEE [1] based TEEs. Currently it is only the ARM
> > +TrustZone based OP-TEE solution that is supported.
> 
> In fact, wouldn't other things be supported by different drivers?
> 
> Perhaps you should name your driver to indicate it is only for ARM?

The OP-TEE Message prototol isn't tied to ARM only and OP-TEE has been
or is used on at least one other architecture (not open sourced though).
I think that only small changes will be needed in the the OP-TEE driver
to support a different architecture as long as shared memory still can
be used. I'd rather keep the name as just "optee" until we know what we
need to adapt to.

> 
> > +
> > +Lowest level of communication with OP-TEE builds on ARM SMC Calling
> > +Convention (SMCCC) [2], which is the foundation for OP-TEE's SMC interface
> > +[3] used internally by the driver. Stacked on top of that is OP-TEE Message
> > +Protocol [4].
> > +
> > +OP-TEE SMC interface provides the basic functions required by SMCCC and some
> > +additional functions specific for OP-TEE. The most interesting functions are:
> > +
> > +- OPTEE_SMC_FUNCID_CALLS_UID (part of SMCCC) returns the version information
> > +  which is then returned by TEE_IOC_VERSION
> > +
> > +- OPTEE_SMC_CALL_GET_OS_UUID returns the particular OP-TEE implementation, used
> > +  to tell, for instance, a TrustZone OP-TEE apart from an OP-TEE running on a
> > +  separate secure co-processor.
> > +
> > +- OPTEE_SMC_CALL_WITH_ARG drives the OP-TEE message protocol
> > +
> > +- OPTEE_SMC_GET_SHM_CONFIG lets the driver and OP-TEE agree on which memory
> > +  range to used for shared memory between Linux and OP-TEE.
> > +
> > +The GlobalPlatform TEE Client API [5] is implemented on top of the generic
> > +TEE API.
> > +
> > +Picture of the relationship between the different components in the
> > +OP-TEE architecture:
> > +
> > +                   U-boot                  Secure world
> > +                   ~~~~~~                  ~~~~~~~~~~~~
> > +                 +------------+           +-------------+
> > +                 | Client     |           | Trusted     |
> > +                 |            |           | Application |
> > +                 +------------+           +-------------+
> > +                       /\                       /\
> > +                       ||                       ||
> > +                       \/                       \/
> > +                 +------------+           +-------------+
> > +                 | TEE        |           | TEE Internal|
> > +                 | uclass     |           | API         |
> > +                 +------------+           +-------------+
> > +                 | OP-TEE     |           | OP-TEE      |
> > +                 | driver     |           | Trusted OS  |
> > +                 +------------+-----------+-------------+
> > +                 |             OP-TEE MSG               |
> > +                 |      SMCCC (OPTEE_SMC_CALL_*)        |
> > +                 +--------------------------------------+
> > +
> > +RPC (Remote Procedure Call) are requests from secure world to the driver.
> > +An RPC is identified by a special range of SMCCC return values from
> > +OPTEE_SMC_CALL_WITH_ARG.
> > +
> > +References
> > +==========
> > +
> > +[1] https://github.com/OP-TEE/optee_os
> > +
> > +[2] http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
> > +
> > +[3] drivers/tee/optee/optee_smc.h
> > +
> > +[4] drivers/tee/optee/optee_msg.h
> > +
> > +[5] http://www.globalplatform.org/specificationsdevice.asp look for
> > +    "TEE Client API Specification v1.0" and click download.
> > --
> > 2.17.1
> >

Thanks for the review,
Jens

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

* [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node
  2018-08-30  0:28   ` Simon Glass
@ 2018-08-31  8:06     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-31  8:06 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 29, 2018 at 06:28:59PM -0600, Simon Glass wrote:
> On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> > Adds a sandbox_tee node to enable the sandbox tee driver in all the
> > sandbox dts files.
> >
> > Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  arch/sandbox/dts/sandbox.dts   | 4 ++++
> >  arch/sandbox/dts/sandbox64.dts | 4 ++++
> >  arch/sandbox/dts/test.dts      | 4 ++++
> >  3 files changed, 12 insertions(+)
> >
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
> BTW it's only the test.dts one that matters for tests. But it's fine
> to add this in the others.

OK.

Thanks,
Jens

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

* [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass)
  2018-08-30  0:29   ` Simon Glass
@ 2018-08-31  8:08     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2018-08-31  8:08 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 29, 2018 at 06:29:02PM -0600, Simon Glass wrote:
> On 23 August 2018 at 04:43, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> > Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> > ---
> >  configs/sandbox64_defconfig        | 1 +
> >  configs/sandbox_defconfig          | 1 +
> >  configs/sandbox_flattree_defconfig | 1 +
> >  configs/sandbox_noblk_defconfig    | 1 +
> >  configs/sandbox_spl_defconfig      | 1 +
> >  5 files changed, 5 insertions(+)
> >
> 
> Can you move this to an 'imply' in arch/Kconfig?

Will do.

Thanks,
Jens

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

* [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application
  2018-08-30  0:29   ` Simon Glass
@ 2018-08-31 12:10     ` Jens Wiklander
  2018-09-26  5:41       ` Simon Glass
  0 siblings, 1 reply; 38+ messages in thread
From: Jens Wiklander @ 2018-08-31 12:10 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Aug 29, 2018 at 06:29:09PM -0600, Simon Glass wrote:
> Hi Jens,
> 
> On 23 August 2018 at 04:43, 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.
> 
> What is AVB? Can you please write it out in full?

AVB stands for Android Verified Boot 2.0. However, Google is a bit picky
about how the name Android is used so I'm trying to avoid using it as
much as possible to stay out of trouble. I'll write it out in the commit
message.

> 
> >
> > Tested-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> > Reviewed-by: Igor Opaniuk <igor.opaniuk@linaro.org>
> > 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 3e6771123ef0..b851d718d32f 100644
> > --- a/include/tee.h
> > +++ b/include/tee.h
> > @@ -48,6 +48,13 @@
> >
> >  #define TEE_ORIGIN_COMMS               0x00000002
> >
> > +struct tee_optee_ta_uuid {
> 
> Comment on this struct. What is it for?

I'll fix.

> 
> > +       u32 time_low;
> > +       u16 time_mid;
> > +       u16 time_hi_and_version;
> > +       u8 clock_seq_and_node[8];
> > +};
> > +
> >  /**
> >   * struct tee_shm - memory shared with the TEE
> >   * @dev:       The TEE device
> > 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*/
> 
> Space before */
> 
> > --
> > 2.17.1
> >

Thanks for the review,
Jens

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

* [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application
  2018-08-31 12:10     ` Jens Wiklander
@ 2018-09-26  5:41       ` Simon Glass
  0 siblings, 0 replies; 38+ messages in thread
From: Simon Glass @ 2018-09-26  5:41 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 31 August 2018 at 06:10, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>
> Hi Simon,
>
> On Wed, Aug 29, 2018 at 06:29:09PM -0600, Simon Glass wrote:
> > Hi Jens,
> >
> > On 23 August 2018 at 04:43, 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.
> >
> > What is AVB? Can you please write it out in full?
>
> AVB stands for Android Verified Boot 2.0. However, Google is a bit picky
> about how the name Android is used so I'm trying to avoid using it as
> much as possible to stay out of trouble. I'll write it out in the commit
> message.

I think it should be somewhere in the docs at least. It looks like
this is what you need to follow:

https://developer.android.com/distribute/marketing-tools/brand-guidelines

Regards,
Simon

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

* [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too
  2018-08-23 10:43 ` [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too Jens Wiklander
  2018-08-30  0:28   ` Simon Glass
@ 2020-01-07  8:49   ` Michal Simek
  2020-01-08  9:44     ` Jens Wiklander
  1 sibling, 1 reply; 38+ messages in thread
From: Michal Simek @ 2020-01-07  8:49 UTC (permalink / raw)
  To: u-boot

Hi Jens and Simon,

čt 23. 8. 2018 v 12:43 odesílatel Jens Wiklander
<jens.wiklander@linaro.org> napsal:
>
> 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
>

I have debug issue which I see on ZynqMP that firmware nodes are
listed in dm tree twice.
I was caused by this patch.

 firmware      1  [ + ]   zynqmp-firmware       |-- zynqmp-firmware
 firmware      2  [ + ]   zynqmp-power          |   `-- zynqmp-power
....
 firmware      3  [   ]   zynqmp-firmware       `-- zynqmp-firmware
 firmware      4  [   ]   zynqmp-power              `-- zynqmp-power

On ZynqMP firmware node needs to be populated early that's why
u-boot,dm-pre-reloc flag is used.
That's why I am curious how to fix this. Revert this patch or add
flags to Jens case or do more checking to avoid creating duplicated
entries of nodes present in firmware node.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too
  2020-01-07  8:49   ` Michal Simek
@ 2020-01-08  9:44     ` Jens Wiklander
  0 siblings, 0 replies; 38+ messages in thread
From: Jens Wiklander @ 2020-01-08  9:44 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Jan 7, 2020 at 9:49 AM Michal Simek <monstr@monstr.eu> wrote:
>
> Hi Jens and Simon,
>
> čt 23. 8. 2018 v 12:43 odesílatel Jens Wiklander
> <jens.wiklander@linaro.org> napsal:
> >
> > 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
> >
>
> I have debug issue which I see on ZynqMP that firmware nodes are
> listed in dm tree twice.
> I was caused by this patch.
>
>  firmware      1  [ + ]   zynqmp-firmware       |-- zynqmp-firmware
>  firmware      2  [ + ]   zynqmp-power          |   `-- zynqmp-power
> ....
>  firmware      3  [   ]   zynqmp-firmware       `-- zynqmp-firmware
>  firmware      4  [   ]   zynqmp-power              `-- zynqmp-power
>
> On ZynqMP firmware node needs to be populated early that's why
> u-boot,dm-pre-reloc flag is used.
> That's why I am curious how to fix this. Revert this patch or add
> flags to Jens case or do more checking to avoid creating duplicated
> entries of nodes present in firmware node.

Reverting may solve the ZynqMP problem, but it will cause new problems
instead so I'd prefer fixing it properly.
I'm not sure if this is best fixed by more flags or by extra checking
when creating the nodes.

Thanks,
Jens

>
> Thanks,
> Michal
>
> --
> Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
> w: www.monstr.eu p: +42-0-721842854
> Maintainer of Linux kernel - Xilinx Microblaze
> Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
> U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

end of thread, other threads:[~2020-01-08  9:44 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-23 10:43 [U-Boot] [PATCH v2 00/15] AVB using OP-TEE Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 01/15] dm: fdt: scan for devices under /firmware too Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2020-01-07  8:49   ` Michal Simek
2020-01-08  9:44     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 02/15] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-23 10:43 ` [U-Boot] [PATCH v2 03/15] cmd: avb: print error message if command fails Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-23 10:43 ` [U-Boot] [PATCH v2 04/15] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 05/15] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-30 13:16     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 06/15] dt/bindings: add bindings for optee Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 07/15] tee: add OP-TEE driver Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-31  7:02     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 08/15] Documentation: tee uclass and op-tee driver Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-31  8:04     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 09/15] test: tee: test TEE uclass Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-23 10:43 ` [U-Boot] [PATCH v2 10/15] sandbox: dt: add sandbox_tee node Jens Wiklander
2018-08-30  0:28   ` Simon Glass
2018-08-31  8:06     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 11/15] configs: sandbox: enable CONFIG_TEE (TEE uclass) Jens Wiklander
2018-08-30  0:29   ` Simon Glass
2018-08-31  8:08     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 12/15] arm: dt: hikey: Add optee node Jens Wiklander
2018-08-30  0:29   ` Simon Glass
2018-08-23 10:43 ` [U-Boot] [PATCH v2 13/15] optee: support routing of rpmb data frames to mmc Jens Wiklander
2018-08-30  0:29   ` Simon Glass
2018-08-30 14:41     ` Jens Wiklander
2018-08-23 10:43 ` [U-Boot] [PATCH v2 14/15] tee: optee: support AVB trusted application Jens Wiklander
2018-08-30  0:29   ` Simon Glass
2018-08-31 12:10     ` Jens Wiklander
2018-09-26  5:41       ` Simon Glass
2018-08-23 10:43 ` [U-Boot] [PATCH v2 15/15] avb_verify: support using OP-TEE TA AVB 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.