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

changes in v3:
* Addressed review comments from Simon Glass
* A few new patches
  - "avb_verify: bugfix avb_ops_free() skipping free"
  - "tee: add sandbox driver"
  - "test_avb: Update pymark.buildconfigspec information for the AVB tests"
  - "avb_verify: support sandbox configuration"
  - "Kconfig: sandbox: enable cmd_avb and dependencies"
* "sandbox: imply CONFIG_TEE (TEE uclass)", replacing
  "configs: sandbox: enable CONFIG_TEE (TEE uclass)"
* Moved sandbox driver to drivers/tee and added code to emulate the AVB TA
* Enabled a few AVB tests (test/py/tests/test_avb.py) for sandbox
* Bugfix tee_find_device()
* Commits "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",
  "Add UCLASS_TEE for Trusted Execution Environment",
  "tee: add OP-TEE driver",
  "Documentation: tee uclass and op-tee driver",
  "test: tee: test TEE uclass",
  "arm: dt: hikey: Add optee node" and
  "sandbox: dt: add sandbox_tee node"
  Reviewed-by: Simon Glass <sjg@chromium.org>

changes in 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 (20):
  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
  avb_verify: bugfix avb_ops_free() skipping free
  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
  arm: dt: hikey: Add optee node
  optee: support routing of rpmb data frames to mmc
  tee: optee: support AVB trusted application
  sandbox: dt: add sandbox_tee node
  sandbox: imply CONFIG_TEE (TEE uclass)
  tee: add sandbox driver
  test: tee: test TEE uclass
  avb_verify: support using OP-TEE TA AVB
  test_avb: Update pymark.buildconfigspec information for the AVB tests
  avb_verify: support sandbox configuration
  Kconfig: sandbox: enable cmd_avb and dependencies

 MAINTAINERS                                   |   7 +
 arch/Kconfig                                  |   5 +
 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                           | 120 +++-
 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/fastboot/Kconfig                      |   2 +
 drivers/mmc/rpmb.c                            | 160 +++++
 drivers/tee/Kconfig                           |  29 +
 drivers/tee/Makefile                          |   5 +
 drivers/tee/optee/Kconfig                     |  27 +
 drivers/tee/optee/Makefile                    |   5 +
 drivers/tee/optee/core.c                      | 662 ++++++++++++++++++
 drivers/tee/optee/optee_msg.h                 | 425 +++++++++++
 drivers/tee/optee/optee_msg_supplicant.h      | 240 +++++++
 drivers/tee/optee/optee_private.h             |  65 ++
 drivers/tee/optee/optee_smc.h                 | 450 ++++++++++++
 drivers/tee/optee/rpmb.c                      | 181 +++++
 drivers/tee/optee/supplicant.c                |  96 +++
 drivers/tee/sandbox.c                         | 299 ++++++++
 drivers/tee/tee-uclass.c                      | 233 ++++++
 include/avb_verify.h                          |  13 +
 include/dm/uclass-id.h                        |   1 +
 include/mmc.h                                 |   2 +
 include/sandboxtee.h                          |  15 +
 include/tee.h                                 | 374 ++++++++++
 include/tee/optee_ta_avb.h                    |  48 ++
 test/dm/Makefile                              |   1 +
 test/dm/tee.c                                 |  98 +++
 test/py/tests/test_avb.py                     |   8 +-
 38 files changed, 3772 insertions(+), 11 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/sandbox.c
 create mode 100644 drivers/tee/tee-uclass.c
 create mode 100644 include/sandboxtee.h
 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] 35+ messages in thread

* [U-Boot] [PATCH v3 01/20] dm: fdt: scan for devices under /firmware too
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 02/20] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 UTC (permalink / raw)
  To: u-boot

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

Reviewed-by: Simon Glass <sjg@chromium.org>
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] 35+ messages in thread

* [U-Boot] [PATCH v3 02/20] cmd: avb read_rb: print rb_idx in hexadecimal
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 01/20] dm: fdt: scan for devices under /firmware too Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 03/20] cmd: avb: print error message if command fails Jens Wiklander
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 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: Simon Glass <sjg@chromium.org>
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] 35+ messages in thread

* [U-Boot] [PATCH v3 03/20] cmd: avb: print error message if command fails
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 01/20] dm: fdt: scan for devices under /firmware too Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 02/20] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 04/20] avb_verify: bugfix avb_ops_free() skipping free Jens Wiklander
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 UTC (permalink / raw)
  To: u-boot

Reviewed-by: Simon Glass <sjg@chromium.org>
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] 35+ messages in thread

* [U-Boot] [PATCH v3 04/20] avb_verify: bugfix avb_ops_free() skipping free
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (2 preceding siblings ...)
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 03/20] cmd: avb: print error message if command fails Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-14 10:53   ` Simon Glass
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 UTC (permalink / raw)
  To: u-boot

Before this patch avb_ops_free() was returning early if supplied "ops"
argument was not NULL. This patch fixes this by inverting the condition.

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

diff --git a/common/avb_verify.c b/common/avb_verify.c
index 20e35ade3029..3a1282a09204 100644
--- a/common/avb_verify.c
+++ b/common/avb_verify.c
@@ -732,7 +732,7 @@ void avb_ops_free(AvbOps *ops)
 {
 	struct AvbOpsData *ops_data;
 
-	if (ops)
+	if (!ops)
 		return;
 
 	ops_data = ops->user_data;
-- 
2.17.1

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

* [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (3 preceding siblings ...)
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 04/20] avb_verify: bugfix avb_ops_free() skipping free Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-14 10:53   ` Simon Glass
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 06/20] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 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] 35+ messages in thread

* [U-Boot] [PATCH v3 06/20] Add UCLASS_TEE for Trusted Execution Environment
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (4 preceding siblings ...)
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 07/20] dt/bindings: add bindings for optee Jens Wiklander
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 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.

Reviewed-by: Simon Glass <sjg@chromium.org>
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      |  11 ++
 drivers/tee/Makefile     |   3 +
 drivers/tee/tee-uclass.c | 209 ++++++++++++++++++++++++
 include/dm/uclass-id.h   |   1 +
 include/tee.h            | 336 +++++++++++++++++++++++++++++++++++++++
 8 files changed, 569 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..f3fc3c2ca790
--- /dev/null
+++ b/drivers/tee/Kconfig
@@ -0,0 +1,11 @@
+# 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). A TEE is a trusted OS running in some secure
+	  environment, for example, TrustZone on ARM cpus, or a separate
+	  secure co-processor etc. See also:
+	  https://en.wikipedia.org/wiki/Trusted_execution_environment
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..1bee54ebf4af
--- /dev/null
+++ b/drivers/tee/tee-uclass.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.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,
+		     uint 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,
+		    uint num_param, struct tee_param *param)
+{
+	return tee_get_ops(dev)->invoke_func(dev, arg, num_param, param);
+}
+
+int __tee_shm_add(struct udevice *dev, ulong align, void *addr, ulong size,
+		  u32 flags, struct tee_shm **shmp)
+{
+	struct tee_shm *shm;
+	void *p = addr;
+	int rc;
+
+	if (flags & TEE_SHM_ALLOC) {
+		if (align)
+			p = memalign(align, size);
+		else
+			p = malloc(size);
+	}
+	if (!p)
+		return -ENOMEM;
+
+	shm = calloc(1, sizeof(*shm));
+	if (!shm) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	shm->dev = dev;
+	shm->addr = p;
+	shm->size = size;
+	shm->flags = flags;
+
+	if (flags & TEE_SHM_SEC_REGISTER) {
+		rc = tee_get_ops(dev)->shm_register(dev, shm);
+		if (rc)
+			goto err;
+	}
+
+	if (flags & TEE_SHM_REGISTER) {
+		struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
+
+		list_add(&shm->link, &priv->list_shm);
+	}
+
+	*shmp = shm;
+
+	return 0;
+err:
+	free(shm);
+	if (flags & TEE_SHM_ALLOC)
+		free(p);
+
+	return rc;
+}
+
+int tee_shm_alloc(struct udevice *dev, ulong size, u32 flags,
+		  struct tee_shm **shmp)
+{
+	u32 f = flags;
+
+	f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER | TEE_SHM_ALLOC;
+
+	return __tee_shm_add(dev, 0, NULL, size, f, shmp);
+}
+
+int tee_shm_register(struct udevice *dev, void *addr, ulong size, u32 flags,
+		     struct tee_shm **shmp)
+{
+	u32 f = flags & ~TEE_SHM_ALLOC;
+
+	f |= TEE_SHM_SEC_REGISTER | TEE_SHM_REGISTER;
+
+	return __tee_shm_add(dev, 0, addr, size, f, shmp);
+}
+
+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_find_first_device(UCLASS_TEE, &dev);
+	else
+		uclass_find_next_device(&dev);
+
+	for (; dev; uclass_find_next_device(&dev)) {
+		if (device_probe(dev))
+			continue;
+		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..b86dbec257b4
--- /dev/null
+++ b/include/tee.h
@@ -0,0 +1,336 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#ifndef __TEE_H
+#define __TEE_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_SECURITY		0xffff000f
+#define TEE_ERROR_OUT_OF_MEMORY		0xffff000c
+#define TEE_ERROR_TARGET_DEAD		0xffff3024
+
+#define TEE_ORIGIN_COMMS		0x00000002
+#define TEE_ORIGIN_TEE			0x00000003
+#define TEE_ORIGIN_TRUSTED_APP		0x00000004
+
+struct udevice;
+/**
+ * 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 - memory reference for a Trusted Application
+ * @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
+ *
+ * Used as a part of struct tee_param, see that for more information.
+ */
+struct tee_param_memref {
+	ulong shm_offs;
+	ulong size;
+	struct tee_shm *shm;
+};
+
+/**
+ * struct tee_param_value - value parameter for a Trusted Application
+ * @a, @b, @c:	Parameters passed by value
+ *
+ * Used as a part of struct tee_param, see that for more information.
+ */
+struct tee_param_value {
+	u64 a;
+	u64 b;
+	u64 c;
+};
+
+/**
+ * struct tee_param - invoke parameter for a Trusted Application
+ * @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
+ *
+ * Parameters to TA are passed using an array of this struct, for
+ * flexibility both value parameters and memory refereces can be used.
+ */
+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,
+ * @open_session:	Opens a session to a Trusted Application in the TEE,
+ * @close_session:	Closes a session to Trusted Application,
+ * @invoke_func:	Invokes a function in a Trusted Application,
+ * @shm_register:	Registers memory shared with the TEE
+ * @shm_unregister:	Unregisters memory shared with the TEE
+ */
+struct tee_driver_ops {
+	/**
+	 * get_version() - Query capabilities of TEE device
+	 * @dev:	The TEE device
+	 * @vers:	Pointer to version data
+	 */
+	void (*get_version)(struct udevice *dev, struct tee_version_data *vers);
+	/**
+	 * 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 (*open_session)(struct udevice *dev,
+			    struct tee_open_session_arg *arg, uint num_param,
+			    struct tee_param *param);
+	/**
+	 * 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 (*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 (*invoke_func)(struct udevice *dev, struct tee_invoke_arg *arg,
+			   uint 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
+ * @shmp:	If the function return 0, this holds the allocated
+ *		struct tee_shm
+ *
+ * returns 0 on success or < 0 on failure.
+ */
+int __tee_shm_add(struct udevice *dev, ulong align, void *addr, ulong size,
+		  u32 flags, struct tee_shm **shmp);
+
+/**
+ * tee_shm_alloc() - Allocate shared memory
+ * @dev:	The TEE device
+ * @size:	Size of memory block
+ * @flags:	TEE_SHM_* above
+ * @shmp:	If the function return 0, this holds the allocated
+ *		struct tee_shm
+ *
+ * returns 0 on success or < 0 on failure.
+ */
+int tee_shm_alloc(struct udevice *dev, ulong size, u32 flags,
+		  struct tee_shm **shmp);
+
+/**
+ * tee_shm_register() - Registers shared memory
+ * @dev:	The TEE device
+ * @addr:	Address of memory block
+ * @size:	Size of memory block
+ * @flags:	TEE_SHM_* above
+ * @shmp:	If the function return 0, this holds the allocated
+ *		struct tee_shm
+ *
+ * returns 0 on success or < 0 on failure.
+ */
+int tee_shm_register(struct udevice *dev, void *addr, ulong size, u32 flags,
+		     struct tee_shm **shmp);
+
+/**
+ * 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, returns != 0 if the device
+ *		matches
+ * @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,
+		     uint 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,
+		    uint num_param, struct tee_param *param);
+
+#endif /* __TEE_H */
-- 
2.17.1

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

* [U-Boot] [PATCH v3 07/20] dt/bindings: add bindings for optee
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (5 preceding siblings ...)
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 06/20] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-14 10:53   ` Simon Glass
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 08/20] tee: add OP-TEE driver Jens Wiklander
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 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] 35+ messages in thread

* [U-Boot] [PATCH v3 08/20] tee: add OP-TEE driver
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (6 preceding siblings ...)
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 07/20] dt/bindings: add bindings for optee Jens Wiklander
@ 2018-09-03 14:46 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 09/20] Documentation: tee uclass and op-tee driver Jens Wiklander
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:46 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

Reviewed-by: Simon Glass <sjg@chromium.org>
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                |  11 +
 drivers/tee/optee/Makefile               |   4 +
 drivers/tee/optee/core.c                 | 654 +++++++++++++++++++++++
 drivers/tee/optee/optee_msg.h            | 425 +++++++++++++++
 drivers/tee/optee/optee_msg_supplicant.h | 240 +++++++++
 drivers/tee/optee/optee_private.h        |  12 +
 drivers/tee/optee/optee_smc.h            | 450 ++++++++++++++++
 drivers/tee/optee/supplicant.c           |  93 ++++
 10 files changed, 1900 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 f3fc3c2ca790..835c256e9239 100644
--- a/drivers/tee/Kconfig
+++ b/drivers/tee/Kconfig
@@ -9,3 +9,13 @@ config TEE
 	  environment, for example, TrustZone on ARM cpus, or a separate
 	  secure co-processor etc. See also:
 	  https://en.wikipedia.org/wiki/Trusted_execution_environment
+
+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..7484e6fea114
--- /dev/null
+++ b/drivers/tee/optee/Kconfig
@@ -0,0 +1,11 @@
+# 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. OP-TEE is a Trusted OS designed primarily to rely on the
+	  ARM TrustZone(R) technology as the underlying hardware isolation
+	  mechanism. This driver can request services from OP-TEE, but also
+	  handle Remote Procedure Calls (RPC) from OP-TEE needed to
+	  execute a service. For more information see: https://www.op-tee.org
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..726382da9bb8
--- /dev/null
+++ b/drivers/tee/optee/core.c
@@ -0,0 +1,654 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <tee.h>
+#include <linux/arm-smccc.h>
+#include <linux/io.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;
+};
+
+/**
+ * reg_pair_to_ptr() - Make a pointer of 2 32-bit values
+ * @reg0:	High bits of the pointer
+ * @reg1:	Low bits of the pointer
+ *
+ * Returns the combined result, note that if a pointer is 32-bit wide @reg0
+ * will be discarded.
+ */
+static void *reg_pair_to_ptr(u32 reg0, u32 reg1)
+{
+	return (void *)(ulong)(((u64)reg0 << 32) | reg1);
+}
+
+/**
+ * reg_pair_from_64() - Split a 64-bit value into two 32-bit values
+ * @reg0:	High bits of @val
+ * @reg1:	Low bits of @val
+ * @val:	The value to split
+ */
+static void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
+{
+	*reg0 = val >> 32;
+	*reg1 = val;
+}
+
+/**
+ * optee_alloc_and_init_page_list() - Provide page list of memory buffer
+ * @buf:		Start of buffer
+ * @len:		Length of buffer
+ * @phys_buf_ptr	Physical pointer with coded offset to page list
+ *
+ * Secure world doesn't share mapping with Normal world (U-Boot in this case)
+ * so physical pointers are needed when sharing pointers.
+ *
+ * Returns a pointer page list on success or NULL on failure
+ */
+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;
+
+	/*
+	 * A Memory buffer is described in chunks of 4k. The list of
+	 * physical addresses has to be represented by a physical pointer
+	 * too and a single list has to start at a 4k page and fit into
+	 * that page. In order to be able to describe large memory buffers
+	 * these 4k pages carrying physical addresses are linked together
+	 * in a list. See OPTEE_MSG_ATTR_NONCONTIG in
+	 * drivers/tee/optee/optee_msg.h for more information.
+	 */
+
+	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 int get_msg_arg(struct udevice *dev, uint num_params,
+		       struct tee_shm **shmp, struct optee_msg_arg **msg_arg)
+{
+	int rc;
+	struct optee_msg_arg *ma;
+
+	rc = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
+			   OPTEE_MSG_GET_ARG_SIZE(num_params), TEE_SHM_ALLOC,
+			   shmp);
+	if (rc)
+		return rc;
+
+	ma = (*shmp)->addr;
+	memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
+	ma->num_params = num_params;
+	*msg_arg = ma;
+
+	return 0;
+}
+
+static int to_msg_param(struct optee_msg_param *msg_params, uint num_params,
+			const struct tee_param *params)
+{
+	uint 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, uint num_params,
+			  const struct optee_msg_param *msg_params)
+{
+	uint 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:
+		if (!__tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
+				   param->a1, TEE_SHM_ALLOC | TEE_SHM_REGISTER,
+				   &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)
+{
+	int rc;
+	struct tee_shm *shm;
+	struct optee_msg_arg *msg_arg;
+
+	rc = get_msg_arg(dev, 0, &shm, &msg_arg);
+	if (rc)
+		return rc;
+
+	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,
+			      uint num_params, struct tee_param *params)
+{
+	int rc;
+	struct tee_shm *shm;
+	struct optee_msg_arg *msg_arg;
+
+	rc = get_msg_arg(dev, num_params + 2, &shm, &msg_arg);
+	if (rc)
+		return rc;
+
+	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,
+			     uint num_params, struct tee_param *params)
+{
+	struct tee_shm *shm;
+	struct optee_msg_arg *msg_arg;
+	int rc;
+
+	rc = get_msg_arg(dev, num_params, &shm, &msg_arg);
+	if (rc)
+		return rc;
+	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;
+
+	rc = get_msg_arg(dev, 1, &shm_arg, &msg_arg);
+	if (rc)
+		return rc;
+
+	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;
+
+	rc = get_msg_arg(dev, 1, &shm_arg, &msg_arg);
+	if (rc)
+		return rc;
+
+	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..24c60960fc47
--- /dev/null
+++ b/drivers/tee/optee/optee_msg.h
@@ -0,0 +1,425 @@
+/* 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 based on
+ * https://github.com/OP-TEE/optee_os/blob/master/core/include/optee_msg.h
+ * and may need to be updated when introducing new features.
+ *
+ * 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..a0fb8063c818
--- /dev/null
+++ b/drivers/tee/optee/optee_msg_supplicant.h
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2016-2018, Linaro Limited
+ */
+
+#ifndef __OPTEE_MSG_SUPPLICANT_H
+#define __OPTEE_MSG_SUPPLICANT_H
+
+/*
+ * This file is based on
+ * https://github.com/OP-TEE/optee_os/blob/master/core/include/optee_msg_supplicant.h
+ * and may need to be updated when introducing new features.
+ */
+
+/*
+ * 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..35adb83afcc7
--- /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..4d643b2599d6
--- /dev/null
+++ b/drivers/tee/optee/optee_smc.h
@@ -0,0 +1,450 @@
+/* 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>
+
+/*
+ * This file is based on
+ * https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/include/sm/optee_smc.h
+ * and may need to be updated when introducing new features.
+ */
+
+#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..2239b1bf7b37
--- /dev/null
+++ b/drivers/tee/optee/supplicant.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#include <common.h>
+#include <log.h>
+#include <tee.h>
+#include <linux/types.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)
+{
+	int rc;
+	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;
+	}
+
+	rc = __tee_shm_add(dev, 0, NULL, arg->params[0].u.value.b,
+			   TEE_SHM_REGISTER | TEE_SHM_ALLOC, &shm);
+	if (rc) {
+		if (rc == -ENOMEM)
+			arg->ret = TEE_ERROR_OUT_OF_MEMORY;
+		else
+			arg->ret = TEE_ERROR_GENERIC;
+		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] 35+ messages in thread

* [U-Boot] [PATCH v3 09/20] Documentation: tee uclass and op-tee driver
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (7 preceding siblings ...)
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 08/20] tee: add OP-TEE driver Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 10/20] arm: dt: hikey: Add optee node Jens Wiklander
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Reviewed-by: Simon Glass <sjg@chromium.org>
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..79e7996a6f5f
--- /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] 35+ messages in thread

* [U-Boot] [PATCH v3 10/20] arm: dt: hikey: Add optee node
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (8 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 09/20] Documentation: tee uclass and op-tee driver Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 11/20] optee: support routing of rpmb data frames to mmc Jens Wiklander
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

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

Reviewed-by: Simon Glass <sjg@chromium.org>
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] 35+ messages in thread

* [U-Boot] [PATCH v3 11/20] optee: support routing of rpmb data frames to mmc
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (9 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 10/20] arm: dt: hikey: Add optee node Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 12/20] tee: optee: support AVB trusted application Jens Wiklander
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 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 |  55 ++++++++-
 drivers/tee/optee/rpmb.c          | 181 ++++++++++++++++++++++++++++++
 drivers/tee/optee/supplicant.c    |   3 +
 5 files changed, 247 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 726382da9bb8..7f870f2f735d 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -315,6 +315,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);
 		}
 	}
@@ -651,4 +658,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 35adb83afcc7..9442d1c176bc 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -6,7 +6,60 @@
 #ifndef __OPTEE_PRIVATE_H
 #define __OPTEE_PRIVATE_H
 
+#include <tee.h>
+#include <log.h>
+
+/**
+ * struct optee_private - OP-TEE driver private data
+ * @rpmb_mmc:		mmc device for the RPMB partition
+ * @rpmb_dev_id:	mmc device id matching @rpmb_mmc
+ * @rpmb_original_part:	the previosly active partition on the mmc device,
+ *			used to restore active the partition when the RPMB
+ *			accesses are finished
+ */
+struct optee_private {
+	struct mmc *rpmb_mmc;
+	int rpmb_dev_id;
+	int 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
+/**
+ * optee_suppl_cmd_rpmb() - route RPMB frames to mmc
+ * @dev:	device with the selected RPMB partition
+ * @arg:	OP-TEE message holding the frames to transmit to the mmc
+ *		and space for the response frames.
+ *
+ * Routes signed (MACed) RPMB frames from OP-TEE Secure OS to MMC and vice
+ * versa to manipulate the RPMB partition.
+ */
+void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg);
+
+/**
+ * optee_suppl_rpmb_release() - release mmc device
+ * @dev:	mmc device
+ *
+ * Releases the mmc device and restores the previously selected partition.
+ */
+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..955155b3f8b1
--- /dev/null
+++ b/drivers/tee/optee/rpmb.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.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;
+	}
+
+	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
+
+	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 2239b1bf7b37..b1ea65bdb2e3 100644
--- a/drivers/tee/optee/supplicant.c
+++ b/drivers/tee/optee/supplicant.c
@@ -85,6 +85,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] 35+ messages in thread

* [U-Boot] [PATCH v3 12/20] tee: optee: support AVB trusted application
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (10 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 11/20] optee: support routing of rpmb data frames to mmc Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 13/20] sandbox: dt: add sandbox_tee node Jens Wiklander
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Adds configuration option OPTEE_TA_AVB and a header file describing the
interface to the Android Verified Boot 2.0 (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 +++++++++++++
 drivers/tee/tee-uclass.c   | 24 +++++++++++++++++++
 include/tee.h              | 38 ++++++++++++++++++++++++++++++
 include/tee/optee_ta_avb.h | 48 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 127 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 7484e6fea114..dbfa7846a30f 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -9,3 +9,19 @@ config OPTEE
 	  mechanism. This driver can request services from OP-TEE, but also
 	  handle Remote Procedure Calls (RPC) from OP-TEE needed to
 	  execute a service. For more information see: https://www.op-tee.org
+
+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/drivers/tee/tee-uclass.c b/drivers/tee/tee-uclass.c
index 1bee54ebf4af..abb88c0fee53 100644
--- a/drivers/tee/tee-uclass.c
+++ b/drivers/tee/tee-uclass.c
@@ -207,3 +207,27 @@ UCLASS_DRIVER(tee) = {
 	.pre_probe = tee_pre_probe,
 	.pre_remove = tee_pre_remove,
 };
+
+void tee_optee_ta_uuid_from_octets(struct tee_optee_ta_uuid *d,
+				   const u8 s[TEE_UUID_LEN])
+{
+	d->time_low = ((u32)s[0] << 24) | ((u32)s[1] << 16) |
+		      ((u32)s[2] << 8) | s[3],
+	d->time_mid = ((u32)s[4] << 8) | s[5];
+	d->time_hi_and_version = ((u32)s[6] << 8) | s[7];
+	memcpy(d->clock_seq_and_node, s + 8, sizeof(d->clock_seq_and_node));
+}
+
+void tee_optee_ta_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));
+}
diff --git a/include/tee.h b/include/tee.h
index b86dbec257b4..98b1c9cc693a 100644
--- a/include/tee.h
+++ b/include/tee.h
@@ -49,6 +49,22 @@
 #define TEE_ORIGIN_TRUSTED_APP		0x00000004
 
 struct udevice;
+
+/**
+ * struct tee_optee_ta_uuid - OP-TEE Trusted Application (TA) UUID format
+ *
+ * Used to identify an OP-TEE TA and define suitable to initialize structs
+ * of this format is distributed with the interface of the TA. The
+ * individual fields of this struct doesn't have any special meaning in
+ * OP-TEE. See RFC4122 for details on the format.
+ */
+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
@@ -333,4 +349,26 @@ int tee_close_session(struct udevice *dev, u32 session);
 int tee_invoke_func(struct udevice *dev, struct tee_invoke_arg *arg,
 		    uint num_param, struct tee_param *param);
 
+/**
+ * tee_optee_ta_uuid_from_octets() - Converts to struct tee_optee_ta_uuid
+ * @d:	Destination struct
+ * @s:	Source UUID octets
+ *
+ * Conversion to a struct tee_optee_ta_uuid represantion from binary octet
+ * representation.
+ */
+void tee_optee_ta_uuid_from_octets(struct tee_optee_ta_uuid *d,
+				   const u8 s[TEE_UUID_LEN]);
+
+/**
+ * tee_optee_ta_uuid_to_octets() - Converts from struct tee_optee_ta_uuid
+ * @d:	Destination UUID octets
+ * @s:	Source struct
+ *
+ * Conversion from a struct tee_optee_ta_uuid represantion to binary octet
+ * representation.
+ */
+void tee_optee_ta_uuid_to_octets(u8 d[TEE_UUID_LEN],
+				 const struct tee_optee_ta_uuid *s);
+
 #endif /* __TEE_H */
diff --git a/include/tee/optee_ta_avb.h b/include/tee/optee_ta_avb.h
new file mode 100644
index 000000000000..074386af19a1
--- /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] 35+ messages in thread

* [U-Boot] [PATCH v3 13/20] sandbox: dt: add sandbox_tee node
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (11 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 12/20] tee: optee: support AVB trusted application Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 14/20] sandbox: imply CONFIG_TEE (TEE uclass) Jens Wiklander
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

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

Reviewed-by: Simon Glass <sjg@chromium.org>
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] 35+ messages in thread

* [U-Boot] [PATCH v3 14/20] sandbox: imply CONFIG_TEE (TEE uclass)
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (12 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 13/20] sandbox: dt: add sandbox_tee node Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-14 10:53   ` Simon Glass
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 15/20] tee: add sandbox driver Jens Wiklander
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/Kconfig b/arch/Kconfig
index bf1b4a9afac6..8f10f3fc06e8 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -91,6 +91,7 @@ config SANDBOX
 	imply HASH_VERIFY
 	imply LZMA
 	imply SCSI
+	imply TEE
 
 config SH
 	bool "SuperH architecture"
-- 
2.17.1

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

* [U-Boot] [PATCH v3 15/20] tee: add sandbox driver
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (13 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 14/20] sandbox: imply CONFIG_TEE (TEE uclass) Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-14 10:53   ` Simon Glass
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 16/20] test: tee: test TEE uclass Jens Wiklander
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Adds a sandboxtee driver which emulates a generic TEE with the OP-TEE
AVB TA.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 drivers/tee/Kconfig       |  12 +-
 drivers/tee/Makefile      |   1 +
 drivers/tee/optee/Kconfig |   2 +-
 drivers/tee/sandbox.c     | 299 ++++++++++++++++++++++++++++++++++++++
 include/sandboxtee.h      |  15 ++
 5 files changed, 326 insertions(+), 3 deletions(-)
 create mode 100644 drivers/tee/sandbox.c
 create mode 100644 include/sandboxtee.h

diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
index 835c256e9239..4697b80913d6 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). A TEE is a trusted OS running in some secure
@@ -14,6 +14,14 @@ if TEE
 
 menu "TEE drivers"
 
+config SANDBOX_TEE
+	bool "Sandbox TEE emulator"
+	depends on SANDBOX
+	default y
+	help
+	  This emulates a generic TEE needed for testing including the AVB
+	  TA.
+
 source "drivers/tee/optee/Kconfig"
 
 endmenu
diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
index 19633b60f235..f72c68c09f33 100644
--- a/drivers/tee/Makefile
+++ b/drivers/tee/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 obj-y += tee-uclass.o
+obj-$(CONFIG_SANDBOX) += sandbox.o
 obj-$(CONFIG_OPTEE) += optee/
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index dbfa7846a30f..d489834df926 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -10,7 +10,7 @@ config OPTEE
 	  handle Remote Procedure Calls (RPC) from OP-TEE needed to
 	  execute a service. For more information see: https://www.op-tee.org
 
-if OPTEE
+if OPTEE || SANDBOX
 
 menu "OP-TEE options"
 
diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
new file mode 100644
index 000000000000..cd073497615f
--- /dev/null
+++ b/drivers/tee/sandbox.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Linaro Limited
+ */
+#include <common.h>
+#include <dm.h>
+#include <sandboxtee.h>
+#include <tee.h>
+#include <tee/optee_ta_avb.h>
+
+/*
+ * The sandbox tee driver tries to emulate a generic TEE with the TA
+ * OPTEE_TA_AVB available.
+ */
+
+struct ta_entry {
+	struct tee_optee_ta_uuid uuid;
+	u32 (*open_session)(uint num_params, struct tee_param *params);
+	u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params);
+};
+
+#ifdef CONFIG_OPTEE_TA_AVB
+static u32 get_attr(uint n, uint num_params, struct tee_param *params)
+{
+	if (n >= num_params)
+		return TEE_PARAM_ATTR_TYPE_NONE;
+
+	return params[n].attr;
+}
+
+static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
+			struct tee_param *params)
+{
+	u8 p[] = { p0, p1, p2, p3};
+	uint n;
+
+	for (n = 0; n < ARRAY_SIZE(p); n++)
+		if (p[n] != get_attr(n, num_params, params))
+			goto bad_params;
+
+	for (; n < num_params; n++)
+		if (get_attr(n, num_params, params))
+			goto bad_params;
+
+	return TEE_SUCCESS;
+
+bad_params:
+	printf("Bad param attrs\n");
+
+	return TEE_ERROR_BAD_PARAMETERS;
+}
+
+static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS];
+static u32 ta_avb_lock_state;
+
+static u32 ta_avb_open_session(uint num_params, struct tee_param *params)
+{
+	/*
+	 * We don't expect additional parameters when opening a session to
+	 * this TA.
+	 */
+	return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+			    TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
+			    num_params, params);
+}
+
+static u32 ta_avb_invoke_func(u32 func, uint num_params,
+			      struct tee_param *params)
+{
+	u32 res;
+	uint slot;
+	u64 val;
+
+	switch (func) {
+	case TA_AVB_CMD_READ_ROLLBACK_INDEX:
+		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+				   TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   num_params, params);
+		if (res)
+			return res;
+
+		slot = params[0].u.value.a;
+		if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
+			printf("Rollback index slot out of bounds %lu\n", slot);
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+
+		val = ta_avb_rollback_indexes[slot];
+		params[1].u.value.a = val >> 32;
+		params[1].u.value.b = val;
+		return TEE_SUCCESS;
+
+	case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
+		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+				   TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   num_params, params);
+		if (res)
+			return res;
+
+		slot = params[0].u.value.a;
+		if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
+			printf("Rollback index slot out of bounds %lu\n", slot);
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+
+		val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
+		if (val < ta_avb_rollback_indexes[slot])
+			return TEE_ERROR_SECURITY;
+
+		ta_avb_rollback_indexes[slot] = val;
+		return TEE_SUCCESS;
+
+	case TA_AVB_CMD_READ_LOCK_STATE:
+		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   num_params, params);
+		if (res)
+			return res;
+
+		params[0].u.value.a = ta_avb_lock_state;
+		return TEE_SUCCESS;
+
+	case TA_AVB_CMD_WRITE_LOCK_STATE:
+		res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   TEE_PARAM_ATTR_TYPE_NONE,
+				   num_params, params);
+		if (res)
+			return res;
+
+		if (ta_avb_lock_state != params[0].u.value.a) {
+			ta_avb_lock_state = params[0].u.value.a;
+			memset(ta_avb_rollback_indexes, 0,
+			       sizeof(ta_avb_rollback_indexes));
+		}
+
+		return TEE_SUCCESS;
+
+	default:
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+}
+#endif /*OPTEE_TA_AVB*/
+
+static const struct ta_entry ta_entries[] = {
+#ifdef CONFIG_OPTEE_TA_AVB
+	{ .uuid = TA_AVB_UUID,
+	  .open_session = ta_avb_open_session,
+	  .invoke_func = ta_avb_invoke_func,
+	},
+#endif
+};
+
+static void sandbox_tee_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 int sandbox_tee_close_session(struct udevice *dev, u32 session)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+
+	if (!state->ta || state->session != session)
+		return -EINVAL;
+
+	state->session = 0;
+	state->ta = NULL;
+
+	return 0;
+}
+
+static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
+{
+	struct tee_optee_ta_uuid u;
+	uint n;
+
+	tee_optee_ta_uuid_from_octets(&u, uuid);
+
+	for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
+		if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
+			return ta_entries + n;
+
+	return NULL;
+}
+
+static int sandbox_tee_open_session(struct udevice *dev,
+				    struct tee_open_session_arg *arg,
+				    uint num_params, struct tee_param *params)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+	const struct ta_entry *ta;
+
+	if (state->ta) {
+		printf("A session is already open\n");
+		return -EBUSY;
+	}
+
+	ta = find_ta_entry(arg->uuid);
+	if (!ta) {
+		printf("Cannot find TA\n");
+		arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
+		arg->ret_origin = TEE_ORIGIN_TEE;
+
+		return 0;
+	}
+
+	arg->ret = ta->open_session(num_params, params);
+	arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
+
+	if (!arg->ret) {
+		state->ta = (void *)ta;
+		state->session = 1;
+		arg->session = state->session;
+	} else {
+		printf("Cannot open session, TA returns error\n");
+	}
+
+	return 0;
+}
+
+static int sandbox_tee_invoke_func(struct udevice *dev,
+				   struct tee_invoke_arg *arg,
+				   uint num_params, struct tee_param *params)
+{
+	struct sandbox_tee_state *state = dev_get_priv(dev);
+	struct ta_entry *ta = state->ta;
+
+	if (!arg->session) {
+		printf("Missing session\n");
+		return -EINVAL;
+	}
+
+	if (!ta) {
+		printf("TA session not available\n");
+		return -EINVAL;
+	}
+
+	if (arg->session != state->session) {
+		printf("Session mismatch\n");
+		return -EINVAL;
+	}
+
+	arg->ret = ta->invoke_func(arg->func, num_params, params);
+	arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
+
+	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),
+};
diff --git a/include/sandboxtee.h b/include/sandboxtee.h
new file mode 100644
index 000000000000..59cbb621820b
--- /dev/null
+++ b/include/sandboxtee.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Linaro Limited
+ */
+
+#ifndef __SANDBOXTEE_H
+#define __SANDBOXTEE_H
+
+struct sandbox_tee_state {
+	u32 session;
+	int num_shms;
+	void *ta;
+};
+
+#endif /*__SANDBOXTEE_H*/
-- 
2.17.1

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

* [U-Boot] [PATCH v3 16/20] test: tee: test TEE uclass
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (14 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 15/20] tee: add sandbox driver Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB Jens Wiklander
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Tests the TEE uclass with a sandbox tee driver.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 test/dm/Makefile |  1 +
 test/dm/tee.c    | 98 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+)
 create mode 100644 test/dm/tee.c

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..ab1c7da9d2d3
--- /dev/null
+++ b/test/dm/tee.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Linaro Limited
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/test.h>
+#include <sandboxtee.h>
+#include <tee.h>
+#include <test/ut.h>
+#include <tee/optee_ta_avb.h>
+
+static int open_session(struct udevice *dev, u32 *session)
+{
+	struct tee_open_session_arg arg;
+	const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
+	int rc;
+
+	memset(&arg, 0, sizeof(arg));
+	tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+	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)
+{
+	struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT };
+	struct tee_invoke_arg arg;
+
+	memset(&arg, 0, sizeof(arg));
+	arg.session = session;
+	arg.func = TA_AVB_CMD_READ_LOCK_STATE;
+
+	if (tee_invoke_func(dev, &arg, 1, &param) || arg.ret)
+		return -1;
+
+	return 0;
+}
+
+static int match(struct tee_version_data *vers, const void *data)
+{
+	return vers->gen_caps & TEE_GEN_CAP_GP;
+}
+
+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);
+	ut_assert(!rc);
+
+	rc = tee_close_session(dev, session);
+	ut_assert(!rc);
+	ut_assert(!state->session);
+
+	ut_assert(!state->num_shms);
+	rc = tee_shm_register(dev, data, sizeof(data), 0, &reg_shm);
+	ut_assert(!rc);
+	ut_assert(state->num_shms == 1);
+
+	rc = tee_shm_alloc(dev, 256, 0, &alloc_shm);
+	ut_assert(!rc);
+	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] 35+ messages in thread

* [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (15 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 16/20] test: tee: test TEE uclass Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-14 10:54   ` Simon Glass
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 18/20] test_avb: Update pymark.buildconfigspec information for the AVB tests Jens Wiklander
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 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  | 118 ++++++++++++++++++++++++++++++++++++++++++-
 doc/README.avb2      |  13 +++++
 include/avb_verify.h |   4 ++
 3 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/common/avb_verify.c b/common/avb_verify.c
index 3a1282a09204..c2248c92514e 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,65 @@ static AvbIOResult validate_vbmeta_public_key(AvbOps *ops,
 	return AVB_IO_RESULT_OK;
 }
 
+#ifdef CONFIG_OPTEE_TA_AVB
+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));
+		tee_optee_ta_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 +670,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 +678,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 +716,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 +752,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 +760,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 +848,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] 35+ messages in thread

* [U-Boot] [PATCH v3 18/20] test_avb: Update pymark.buildconfigspec information for the AVB tests
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (16 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-14 10:54   ` Simon Glass
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration Jens Wiklander
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 20/20] Kconfig: sandbox: enable cmd_avb and dependencies Jens Wiklander
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Update the pymark.buildconfigspec to depend on 'cmd_mmc' in addition to
'cmd_avb' for those tests that needs more a more complete MMC
implementation or the "mmc" command.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 test/py/tests/test_avb.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/test/py/tests/test_avb.py b/test/py/tests/test_avb.py
index 7996e4845db3..9683fd80d074 100644
--- a/test/py/tests/test_avb.py
+++ b/test/py/tests/test_avb.py
@@ -23,7 +23,7 @@ mmc_dev = 1
 temp_addr = 0x90000000
 temp_addr2 = 0x90002000
 
- at pytest.mark.buildconfigspec('cmd_avb')
+ at pytest.mark.buildconfigspec('cmd_avb', 'cmd_mmc')
 def test_avb_verify(u_boot_console):
     """Run AVB 2.0 boot verification chain with avb subset of commands
     """
@@ -36,7 +36,7 @@ def test_avb_verify(u_boot_console):
     assert response.find(success_str)
 
 
- at pytest.mark.buildconfigspec('cmd_avb')
+ at pytest.mark.buildconfigspec('cmd_avb', 'cmd_mmc')
 def test_avb_mmc_uuid(u_boot_console):
     """Check if 'avb get_uuid' works, compare results with
     'part list mmc 1' output
@@ -78,6 +78,7 @@ def test_avb_read_rb(u_boot_console):
     assert response == ''
 
     response = u_boot_console.run_command('avb read_rb 1')
+    assert response == 'Rollback index: 0'
 
 
 @pytest.mark.buildconfigspec('cmd_avb')
@@ -89,9 +90,10 @@ def test_avb_is_unlocked(u_boot_console):
     assert response == ''
 
     response = u_boot_console.run_command('avb is_unlocked')
+    assert response == 'Unlocked = 1'
 
 
- at pytest.mark.buildconfigspec('cmd_avb')
+ at pytest.mark.buildconfigspec('cmd_avb', 'cmd_mmc')
 def test_avb_mmc_read(u_boot_console):
     """Test mmc read operation
     """
-- 
2.17.1

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

* [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (17 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 18/20] test_avb: Update pymark.buildconfigspec information for the AVB tests Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-14 10:54   ` Simon Glass
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 20/20] Kconfig: sandbox: enable cmd_avb and dependencies Jens Wiklander
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

With CONFIG_SANDBOX malloc a buffer in get_sector_buf() and return that
instead of returning CONFIG_FASTBOOT_BUF_ADDR since there's no such
buffer reserved.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 include/avb_verify.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/avb_verify.h b/include/avb_verify.h
index a532a2331aea..7b95409d247e 100644
--- a/include/avb_verify.h
+++ b/include/avb_verify.h
@@ -76,7 +76,16 @@ static inline size_t get_sector_buf_size(void)
 
 static inline void *get_sector_buf(void)
 {
+#ifdef CONFIG_SANDBOX
+	static void *p;
+
+	if (!p)
+		p = avb_malloc_(get_sector_buf_size());
+
+	return p;
+#else
 	return (void *)CONFIG_FASTBOOT_BUF_ADDR;
+#endif
 }
 
 static inline bool is_buf_unaligned(void *buffer)
-- 
2.17.1

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

* [U-Boot] [PATCH v3 20/20] Kconfig: sandbox: enable cmd_avb and dependencies
  2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
                   ` (18 preceding siblings ...)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration Jens Wiklander
@ 2018-09-03 14:47 ` Jens Wiklander
  2018-09-14 10:54   ` Simon Glass
  19 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-03 14:47 UTC (permalink / raw)
  To: u-boot

Enables cmd_avb and its dependencies need to run the AVB tests.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 arch/Kconfig             | 4 ++++
 drivers/fastboot/Kconfig | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/arch/Kconfig b/arch/Kconfig
index 8f10f3fc06e8..543362578f50 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -92,6 +92,10 @@ config SANDBOX
 	imply LZMA
 	imply SCSI
 	imply TEE
+	imply AVB_VERIFY
+	imply LIBAVB
+	imply CMD_AVB
+	imply UDP_FUNCTION_FASTBOOT
 
 config SH
 	bool "SuperH architecture"
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index bc25ea1d9c7a..d63ecdd27e4b 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -35,6 +35,7 @@ config FASTBOOT_BUF_ADDR
 				ROCKCHIP_RK3399
 	default 0x280000 if ROCKCHIP_RK3368
 	default 0x100000 if ARCH_ZYNQMP
+	default 0 if SANDBOX
 	help
 	  The fastboot protocol requires a large memory buffer for
 	  downloads. Define this to the starting RAM address to use for
@@ -45,6 +46,7 @@ config FASTBOOT_BUF_SIZE
 	default 0x8000000 if ARCH_ROCKCHIP
 	default 0x6000000 if ARCH_ZYNQMP
 	default 0x2000000 if ARCH_SUNXI
+	default 0x8192 if SANDBOX
 	default 0x7000000
 	help
 	  The fastboot protocol requires a large memory buffer for
-- 
2.17.1

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

* [U-Boot] [PATCH v3 04/20] avb_verify: bugfix avb_ops_free() skipping free
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 04/20] avb_verify: bugfix avb_ops_free() skipping free Jens Wiklander
@ 2018-09-14 10:53   ` Simon Glass
  0 siblings, 0 replies; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:53 UTC (permalink / raw)
  To: u-boot

On 3 September 2018 at 16:46, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Before this patch avb_ops_free() was returning early if supplied "ops"
> argument was not NULL. This patch fixes this by inverting the condition.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  common/avb_verify.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

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

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

* [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
@ 2018-09-14 10:53   ` Simon Glass
  2018-09-25  6:14     ` Jens Wiklander
  0 siblings, 1 reply; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:53 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 3 September 2018 at 16:46, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> 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/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);

Please can you add a full comment to this function? All header-file
functions should be commented.

>  #ifdef CONFIG_CMD_BKOPS_ENABLE
>  int mmc_set_bkops_enable(struct mmc *mmc);
>  #endif
> --
> 2.17.1
>

Regards,
Simon

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

* [U-Boot] [PATCH v3 07/20] dt/bindings: add bindings for optee
  2018-09-03 14:46 ` [U-Boot] [PATCH v3 07/20] dt/bindings: add bindings for optee Jens Wiklander
@ 2018-09-14 10:53   ` Simon Glass
  0 siblings, 0 replies; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:53 UTC (permalink / raw)
  To: u-boot

On 3 September 2018 at 16:46, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> 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

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

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

* [U-Boot] [PATCH v3 14/20] sandbox: imply CONFIG_TEE (TEE uclass)
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 14/20] sandbox: imply CONFIG_TEE (TEE uclass) Jens Wiklander
@ 2018-09-14 10:53   ` Simon Glass
  0 siblings, 0 replies; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:53 UTC (permalink / raw)
  To: u-boot

On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  arch/Kconfig | 1 +
>  1 file changed, 1 insertion(+)

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

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

* [U-Boot] [PATCH v3 15/20] tee: add sandbox driver
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 15/20] tee: add sandbox driver Jens Wiklander
@ 2018-09-14 10:53   ` Simon Glass
  2018-09-25  7:33     ` Jens Wiklander
  0 siblings, 1 reply; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:53 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Adds a sandboxtee driver which emulates a generic TEE with the OP-TEE

sandbox tee

> AVB TA.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  drivers/tee/Kconfig       |  12 +-
>  drivers/tee/Makefile      |   1 +
>  drivers/tee/optee/Kconfig |   2 +-
>  drivers/tee/sandbox.c     | 299 ++++++++++++++++++++++++++++++++++++++
>  include/sandboxtee.h      |  15 ++
>  5 files changed, 326 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/tee/sandbox.c
>  create mode 100644 include/sandboxtee.h

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

nits below.

>
> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
> index 835c256e9239..4697b80913d6 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). A TEE is a trusted OS running in some secure
> @@ -14,6 +14,14 @@ if TEE
>
>  menu "TEE drivers"
>
> +config SANDBOX_TEE
> +       bool "Sandbox TEE emulator"
> +       depends on SANDBOX
> +       default y
> +       help
> +         This emulates a generic TEE needed for testing including the AVB
> +         TA.

Can you please expand this? What features does it implement? How do
you access it from the U-Boot command line?

> +
>  source "drivers/tee/optee/Kconfig"
>
>  endmenu
> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
> index 19633b60f235..f72c68c09f33 100644
> --- a/drivers/tee/Makefile
> +++ b/drivers/tee/Makefile
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0+
>
>  obj-y += tee-uclass.o
> +obj-$(CONFIG_SANDBOX) += sandbox.o
>  obj-$(CONFIG_OPTEE) += optee/
> diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
> index dbfa7846a30f..d489834df926 100644
> --- a/drivers/tee/optee/Kconfig
> +++ b/drivers/tee/optee/Kconfig
> @@ -10,7 +10,7 @@ config OPTEE
>           handle Remote Procedure Calls (RPC) from OP-TEE needed to
>           execute a service. For more information see: https://www.op-tee.org
>
> -if OPTEE
> +if OPTEE || SANDBOX
>
>  menu "OP-TEE options"
>
> diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
> new file mode 100644
> index 000000000000..cd073497615f
> --- /dev/null
> +++ b/drivers/tee/sandbox.c
> @@ -0,0 +1,299 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Linaro Limited
> + */
> +#include <common.h>
> +#include <dm.h>
> +#include <sandboxtee.h>

Could this go in asm/ ?

> +#include <tee.h>
> +#include <tee/optee_ta_avb.h>
> +
> +/*
> + * The sandbox tee driver tries to emulate a generic TEE with the TA
> + * OPTEE_TA_AVB available.

What is TEE?

What is TA?

Please expand out the names once in this comment so people can see
immediately what you are referring to.

> + */
> +



> +struct ta_entry {

What is this struct for? Please add a comment

> +       struct tee_optee_ta_uuid uuid;
> +       u32 (*open_session)(uint num_params, struct tee_param *params);
> +       u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params);
> +};
> +
> +#ifdef CONFIG_OPTEE_TA_AVB
> +static u32 get_attr(uint n, uint num_params, struct tee_param *params)
> +{
> +       if (n >= num_params)
> +               return TEE_PARAM_ATTR_TYPE_NONE;
> +
> +       return params[n].attr;
> +}
> +
> +static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
> +                       struct tee_param *params)
> +{
> +       u8 p[] = { p0, p1, p2, p3};
> +       uint n;
> +
> +       for (n = 0; n < ARRAY_SIZE(p); n++)
> +               if (p[n] != get_attr(n, num_params, params))
> +                       goto bad_params;
> +
> +       for (; n < num_params; n++)
> +               if (get_attr(n, num_params, params))
> +                       goto bad_params;
> +
> +       return TEE_SUCCESS;
> +
> +bad_params:
> +       printf("Bad param attrs\n");
> +
> +       return TEE_ERROR_BAD_PARAMETERS;
> +}
> +
> +static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS];
> +static u32 ta_avb_lock_state;
> +
> +static u32 ta_avb_open_session(uint num_params, struct tee_param *params)
> +{
> +       /*
> +        * We don't expect additional parameters when opening a session to
> +        * this TA.
> +        */
> +       return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
> +                           TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
> +                           num_params, params);
> +}
> +
> +static u32 ta_avb_invoke_func(u32 func, uint num_params,
> +                             struct tee_param *params)
> +{
> +       u32 res;
> +       uint slot;
> +       u64 val;
> +
> +       switch (func) {
> +       case TA_AVB_CMD_READ_ROLLBACK_INDEX:
> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
> +                                  TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  num_params, params);
> +               if (res)
> +                       return res;
> +
> +               slot = params[0].u.value.a;
> +               if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
> +                       printf("Rollback index slot out of bounds %lu\n", slot);
> +                       return TEE_ERROR_BAD_PARAMETERS;
> +               }
> +
> +               val = ta_avb_rollback_indexes[slot];
> +               params[1].u.value.a = val >> 32;
> +               params[1].u.value.b = val;
> +               return TEE_SUCCESS;
> +
> +       case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
> +                                  TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  num_params, params);
> +               if (res)
> +                       return res;
> +
> +               slot = params[0].u.value.a;
> +               if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
> +                       printf("Rollback index slot out of bounds %lu\n", slot);
> +                       return TEE_ERROR_BAD_PARAMETERS;
> +               }
> +
> +               val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
> +               if (val < ta_avb_rollback_indexes[slot])
> +                       return TEE_ERROR_SECURITY;
> +
> +               ta_avb_rollback_indexes[slot] = val;
> +               return TEE_SUCCESS;
> +
> +       case TA_AVB_CMD_READ_LOCK_STATE:
> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  num_params, params);
> +               if (res)
> +                       return res;
> +
> +               params[0].u.value.a = ta_avb_lock_state;
> +               return TEE_SUCCESS;
> +
> +       case TA_AVB_CMD_WRITE_LOCK_STATE:
> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  TEE_PARAM_ATTR_TYPE_NONE,
> +                                  num_params, params);
> +               if (res)
> +                       return res;
> +
> +               if (ta_avb_lock_state != params[0].u.value.a) {
> +                       ta_avb_lock_state = params[0].u.value.a;
> +                       memset(ta_avb_rollback_indexes, 0,
> +                              sizeof(ta_avb_rollback_indexes));
> +               }
> +
> +               return TEE_SUCCESS;
> +
> +       default:
> +               return TEE_ERROR_NOT_SUPPORTED;
> +       }
> +}
> +#endif /*OPTEE_TA_AVB*/
> +
> +static const struct ta_entry ta_entries[] = {
> +#ifdef CONFIG_OPTEE_TA_AVB
> +       { .uuid = TA_AVB_UUID,
> +         .open_session = ta_avb_open_session,
> +         .invoke_func = ta_avb_invoke_func,
> +       },
> +#endif
> +};
> +
> +static void sandbox_tee_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 int sandbox_tee_close_session(struct udevice *dev, u32 session)
> +{
> +       struct sandbox_tee_state *state = dev_get_priv(dev);
> +
> +       if (!state->ta || state->session != session)
> +               return -EINVAL;
> +
> +       state->session = 0;
> +       state->ta = NULL;
> +
> +       return 0;
> +}
> +
> +static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
> +{
> +       struct tee_optee_ta_uuid u;
> +       uint n;
> +
> +       tee_optee_ta_uuid_from_octets(&u, uuid);
> +
> +       for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
> +               if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
> +                       return ta_entries + n;
> +
> +       return NULL;
> +}
> +
> +static int sandbox_tee_open_session(struct udevice *dev,
> +                                   struct tee_open_session_arg *arg,
> +                                   uint num_params, struct tee_param *params)
> +{
> +       struct sandbox_tee_state *state = dev_get_priv(dev);
> +       const struct ta_entry *ta;
> +
> +       if (state->ta) {
> +               printf("A session is already open\n");
> +               return -EBUSY;
> +       }
> +
> +       ta = find_ta_entry(arg->uuid);
> +       if (!ta) {
> +               printf("Cannot find TA\n");
> +               arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
> +               arg->ret_origin = TEE_ORIGIN_TEE;
> +
> +               return 0;
> +       }
> +
> +       arg->ret = ta->open_session(num_params, params);
> +       arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
> +
> +       if (!arg->ret) {
> +               state->ta = (void *)ta;
> +               state->session = 1;
> +               arg->session = state->session;
> +       } else {
> +               printf("Cannot open session, TA returns error\n");
> +       }
> +
> +       return 0;
> +}
> +
> +static int sandbox_tee_invoke_func(struct udevice *dev,
> +                                  struct tee_invoke_arg *arg,
> +                                  uint num_params, struct tee_param *params)
> +{
> +       struct sandbox_tee_state *state = dev_get_priv(dev);
> +       struct ta_entry *ta = state->ta;
> +
> +       if (!arg->session) {
> +               printf("Missing session\n");
> +               return -EINVAL;
> +       }
> +
> +       if (!ta) {
> +               printf("TA session not available\n");
> +               return -EINVAL;
> +       }
> +
> +       if (arg->session != state->session) {
> +               printf("Session mismatch\n");
> +               return -EINVAL;
> +       }
> +
> +       arg->ret = ta->invoke_func(arg->func, num_params, params);
> +       arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
> +
> +       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),
> +};
> diff --git a/include/sandboxtee.h b/include/sandboxtee.h
> new file mode 100644
> index 000000000000..59cbb621820b
> --- /dev/null
> +++ b/include/sandboxtee.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2018 Linaro Limited
> + */
> +
> +#ifndef __SANDBOXTEE_H
> +#define __SANDBOXTEE_H
> +
> +struct sandbox_tee_state {
> +       u32 session;
> +       int num_shms;
> +       void *ta;

struct/members need comments

> +};
> +
> +#endif /*__SANDBOXTEE_H*/
> --
> 2.17.1
>

Regards,
Simon

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

* [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB Jens Wiklander
@ 2018-09-14 10:54   ` Simon Glass
  2018-09-25  7:34     ` Jens Wiklander
  0 siblings, 1 reply; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:54 UTC (permalink / raw)
  To: u-boot

On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> With CONFIG_OPTEE_TA_AVB use the trusted application AVB provided by
> OP-TEE to manage rollback indexes and device lock status.

Should this be device-lock status?

>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  common/avb_verify.c  | 118 ++++++++++++++++++++++++++++++++++++++++++-
>  doc/README.avb2      |  13 +++++
>  include/avb_verify.h |   4 ++
>  3 files changed, 134 insertions(+), 1 deletion(-)

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

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

* [U-Boot] [PATCH v3 18/20] test_avb: Update pymark.buildconfigspec information for the AVB tests
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 18/20] test_avb: Update pymark.buildconfigspec information for the AVB tests Jens Wiklander
@ 2018-09-14 10:54   ` Simon Glass
  0 siblings, 0 replies; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:54 UTC (permalink / raw)
  To: u-boot

On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Update the pymark.buildconfigspec to depend on 'cmd_mmc' in addition to
> 'cmd_avb' for those tests that needs more a more complete MMC
> implementation or the "mmc" command.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  test/py/tests/test_avb.py | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)

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

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

* [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration Jens Wiklander
@ 2018-09-14 10:54   ` Simon Glass
  2018-09-25 10:50     ` Jens Wiklander
  0 siblings, 1 reply; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:54 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> With CONFIG_SANDBOX malloc a buffer in get_sector_buf() and return that
> instead of returning CONFIG_FASTBOOT_BUF_ADDR since there's no such
> buffer reserved.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  include/avb_verify.h | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/include/avb_verify.h b/include/avb_verify.h
> index a532a2331aea..7b95409d247e 100644
> --- a/include/avb_verify.h
> +++ b/include/avb_verify.h
> @@ -76,7 +76,16 @@ static inline size_t get_sector_buf_size(void)
>
>  static inline void *get_sector_buf(void)
>  {
> +#ifdef CONFIG_SANDBOX
> +       static void *p;
> +
> +       if (!p)
> +               p = avb_malloc_(get_sector_buf_size());
> +
> +       return p;
> +#else
>         return (void *)CONFIG_FASTBOOT_BUF_ADDR;

Can you not define this on sandbox? We don't want sandbox to have
special-case code if we can avoid it.

If you do define it, you should change the code to:

return map_sysmem(CONFIG_..., size);

which works on sandbox and other archs too.

> +#endif
>  }
>
>  static inline bool is_buf_unaligned(void *buffer)
> --
> 2.17.1
>

Regards,
Simon

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

* [U-Boot] [PATCH v3 20/20] Kconfig: sandbox: enable cmd_avb and dependencies
  2018-09-03 14:47 ` [U-Boot] [PATCH v3 20/20] Kconfig: sandbox: enable cmd_avb and dependencies Jens Wiklander
@ 2018-09-14 10:54   ` Simon Glass
  0 siblings, 0 replies; 35+ messages in thread
From: Simon Glass @ 2018-09-14 10:54 UTC (permalink / raw)
  To: u-boot

On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Enables cmd_avb and its dependencies need to run the AVB tests.
>
> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
> ---
>  arch/Kconfig             | 4 ++++
>  drivers/fastboot/Kconfig | 2 ++
>  2 files changed, 6 insertions(+)

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

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

* [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames()
  2018-09-14 10:53   ` Simon Glass
@ 2018-09-25  6:14     ` Jens Wiklander
  0 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-25  6:14 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, Sep 14, 2018 at 12:53 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Jens,
>
> On 3 September 2018 at 16:46, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> 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/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);
>
> Please can you add a full comment to this function? All header-file
> functions should be commented.

I'll fix.

Thanks,
Jens

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

* [U-Boot] [PATCH v3 15/20] tee: add sandbox driver
  2018-09-14 10:53   ` Simon Glass
@ 2018-09-25  7:33     ` Jens Wiklander
  2018-10-02 11:22       ` Simon Glass
  0 siblings, 1 reply; 35+ messages in thread
From: Jens Wiklander @ 2018-09-25  7:33 UTC (permalink / raw)
  To: u-boot

Hi Simon,

I have one question inline below.

On Fri, Sep 14, 2018 at 12:53 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Jens,
>
> On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> Adds a sandboxtee driver which emulates a generic TEE with the OP-TEE
>
> sandbox tee
>
>> AVB TA.
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  drivers/tee/Kconfig       |  12 +-
>>  drivers/tee/Makefile      |   1 +
>>  drivers/tee/optee/Kconfig |   2 +-
>>  drivers/tee/sandbox.c     | 299 ++++++++++++++++++++++++++++++++++++++
>>  include/sandboxtee.h      |  15 ++
>>  5 files changed, 326 insertions(+), 3 deletions(-)
>>  create mode 100644 drivers/tee/sandbox.c
>>  create mode 100644 include/sandboxtee.h
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> nits below.
>
>>
>> diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
>> index 835c256e9239..4697b80913d6 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). A TEE is a trusted OS running in some secure
>> @@ -14,6 +14,14 @@ if TEE
>>
>>  menu "TEE drivers"
>>
>> +config SANDBOX_TEE
>> +       bool "Sandbox TEE emulator"
>> +       depends on SANDBOX
>> +       default y
>> +       help
>> +         This emulates a generic TEE needed for testing including the AVB
>> +         TA.
>
> Can you please expand this? What features does it implement? How do
> you access it from the U-Boot command line?

I'll expand it.

>
>> +
>>  source "drivers/tee/optee/Kconfig"
>>
>>  endmenu
>> diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
>> index 19633b60f235..f72c68c09f33 100644
>> --- a/drivers/tee/Makefile
>> +++ b/drivers/tee/Makefile
>> @@ -1,4 +1,5 @@
>>  # SPDX-License-Identifier: GPL-2.0+
>>
>>  obj-y += tee-uclass.o
>> +obj-$(CONFIG_SANDBOX) += sandbox.o
>>  obj-$(CONFIG_OPTEE) += optee/
>> diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
>> index dbfa7846a30f..d489834df926 100644
>> --- a/drivers/tee/optee/Kconfig
>> +++ b/drivers/tee/optee/Kconfig
>> @@ -10,7 +10,7 @@ config OPTEE
>>           handle Remote Procedure Calls (RPC) from OP-TEE needed to
>>           execute a service. For more information see: https://www.op-tee.org
>>
>> -if OPTEE
>> +if OPTEE || SANDBOX
>>
>>  menu "OP-TEE options"
>>
>> diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
>> new file mode 100644
>> index 000000000000..cd073497615f
>> --- /dev/null
>> +++ b/drivers/tee/sandbox.c
>> @@ -0,0 +1,299 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Copyright (C) 2018 Linaro Limited
>> + */
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <sandboxtee.h>
>
> Could this go in asm/ ?

I don't understand. What should go into asm/ and which directory is that?

>
>> +#include <tee.h>
>> +#include <tee/optee_ta_avb.h>
>> +
>> +/*
>> + * The sandbox tee driver tries to emulate a generic TEE with the TA
>> + * OPTEE_TA_AVB available.
>
> What is TEE?
>
> What is TA?
>
> Please expand out the names once in this comment so people can see
> immediately what you are referring to.
>
>> + */
>> +
>
>
>
>> +struct ta_entry {
>
> What is this struct for? Please add a comment

OK

>
>> +       struct tee_optee_ta_uuid uuid;
>> +       u32 (*open_session)(uint num_params, struct tee_param *params);
>> +       u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params);
>> +};
>> +
>> +#ifdef CONFIG_OPTEE_TA_AVB
>> +static u32 get_attr(uint n, uint num_params, struct tee_param *params)
>> +{
>> +       if (n >= num_params)
>> +               return TEE_PARAM_ATTR_TYPE_NONE;
>> +
>> +       return params[n].attr;
>> +}
>> +
>> +static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
>> +                       struct tee_param *params)
>> +{
>> +       u8 p[] = { p0, p1, p2, p3};
>> +       uint n;
>> +
>> +       for (n = 0; n < ARRAY_SIZE(p); n++)
>> +               if (p[n] != get_attr(n, num_params, params))
>> +                       goto bad_params;
>> +
>> +       for (; n < num_params; n++)
>> +               if (get_attr(n, num_params, params))
>> +                       goto bad_params;
>> +
>> +       return TEE_SUCCESS;
>> +
>> +bad_params:
>> +       printf("Bad param attrs\n");
>> +
>> +       return TEE_ERROR_BAD_PARAMETERS;
>> +}
>> +
>> +static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS];
>> +static u32 ta_avb_lock_state;
>> +
>> +static u32 ta_avb_open_session(uint num_params, struct tee_param *params)
>> +{
>> +       /*
>> +        * We don't expect additional parameters when opening a session to
>> +        * this TA.
>> +        */
>> +       return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
>> +                           TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
>> +                           num_params, params);
>> +}
>> +
>> +static u32 ta_avb_invoke_func(u32 func, uint num_params,
>> +                             struct tee_param *params)
>> +{
>> +       u32 res;
>> +       uint slot;
>> +       u64 val;
>> +
>> +       switch (func) {
>> +       case TA_AVB_CMD_READ_ROLLBACK_INDEX:
>> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
>> +                                  TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  num_params, params);
>> +               if (res)
>> +                       return res;
>> +
>> +               slot = params[0].u.value.a;
>> +               if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
>> +                       printf("Rollback index slot out of bounds %lu\n", slot);
>> +                       return TEE_ERROR_BAD_PARAMETERS;
>> +               }
>> +
>> +               val = ta_avb_rollback_indexes[slot];
>> +               params[1].u.value.a = val >> 32;
>> +               params[1].u.value.b = val;
>> +               return TEE_SUCCESS;
>> +
>> +       case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
>> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
>> +                                  TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  num_params, params);
>> +               if (res)
>> +                       return res;
>> +
>> +               slot = params[0].u.value.a;
>> +               if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
>> +                       printf("Rollback index slot out of bounds %lu\n", slot);
>> +                       return TEE_ERROR_BAD_PARAMETERS;
>> +               }
>> +
>> +               val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
>> +               if (val < ta_avb_rollback_indexes[slot])
>> +                       return TEE_ERROR_SECURITY;
>> +
>> +               ta_avb_rollback_indexes[slot] = val;
>> +               return TEE_SUCCESS;
>> +
>> +       case TA_AVB_CMD_READ_LOCK_STATE:
>> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  num_params, params);
>> +               if (res)
>> +                       return res;
>> +
>> +               params[0].u.value.a = ta_avb_lock_state;
>> +               return TEE_SUCCESS;
>> +
>> +       case TA_AVB_CMD_WRITE_LOCK_STATE:
>> +               res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  TEE_PARAM_ATTR_TYPE_NONE,
>> +                                  num_params, params);
>> +               if (res)
>> +                       return res;
>> +
>> +               if (ta_avb_lock_state != params[0].u.value.a) {
>> +                       ta_avb_lock_state = params[0].u.value.a;
>> +                       memset(ta_avb_rollback_indexes, 0,
>> +                              sizeof(ta_avb_rollback_indexes));
>> +               }
>> +
>> +               return TEE_SUCCESS;
>> +
>> +       default:
>> +               return TEE_ERROR_NOT_SUPPORTED;
>> +       }
>> +}
>> +#endif /*OPTEE_TA_AVB*/
>> +
>> +static const struct ta_entry ta_entries[] = {
>> +#ifdef CONFIG_OPTEE_TA_AVB
>> +       { .uuid = TA_AVB_UUID,
>> +         .open_session = ta_avb_open_session,
>> +         .invoke_func = ta_avb_invoke_func,
>> +       },
>> +#endif
>> +};
>> +
>> +static void sandbox_tee_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 int sandbox_tee_close_session(struct udevice *dev, u32 session)
>> +{
>> +       struct sandbox_tee_state *state = dev_get_priv(dev);
>> +
>> +       if (!state->ta || state->session != session)
>> +               return -EINVAL;
>> +
>> +       state->session = 0;
>> +       state->ta = NULL;
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
>> +{
>> +       struct tee_optee_ta_uuid u;
>> +       uint n;
>> +
>> +       tee_optee_ta_uuid_from_octets(&u, uuid);
>> +
>> +       for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
>> +               if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
>> +                       return ta_entries + n;
>> +
>> +       return NULL;
>> +}
>> +
>> +static int sandbox_tee_open_session(struct udevice *dev,
>> +                                   struct tee_open_session_arg *arg,
>> +                                   uint num_params, struct tee_param *params)
>> +{
>> +       struct sandbox_tee_state *state = dev_get_priv(dev);
>> +       const struct ta_entry *ta;
>> +
>> +       if (state->ta) {
>> +               printf("A session is already open\n");
>> +               return -EBUSY;
>> +       }
>> +
>> +       ta = find_ta_entry(arg->uuid);
>> +       if (!ta) {
>> +               printf("Cannot find TA\n");
>> +               arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
>> +               arg->ret_origin = TEE_ORIGIN_TEE;
>> +
>> +               return 0;
>> +       }
>> +
>> +       arg->ret = ta->open_session(num_params, params);
>> +       arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
>> +
>> +       if (!arg->ret) {
>> +               state->ta = (void *)ta;
>> +               state->session = 1;
>> +               arg->session = state->session;
>> +       } else {
>> +               printf("Cannot open session, TA returns error\n");
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int sandbox_tee_invoke_func(struct udevice *dev,
>> +                                  struct tee_invoke_arg *arg,
>> +                                  uint num_params, struct tee_param *params)
>> +{
>> +       struct sandbox_tee_state *state = dev_get_priv(dev);
>> +       struct ta_entry *ta = state->ta;
>> +
>> +       if (!arg->session) {
>> +               printf("Missing session\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (!ta) {
>> +               printf("TA session not available\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (arg->session != state->session) {
>> +               printf("Session mismatch\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       arg->ret = ta->invoke_func(arg->func, num_params, params);
>> +       arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
>> +
>> +       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),
>> +};
>> diff --git a/include/sandboxtee.h b/include/sandboxtee.h
>> new file mode 100644
>> index 000000000000..59cbb621820b
>> --- /dev/null
>> +++ b/include/sandboxtee.h
>> @@ -0,0 +1,15 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * Copyright (C) 2018 Linaro Limited
>> + */
>> +
>> +#ifndef __SANDBOXTEE_H
>> +#define __SANDBOXTEE_H
>> +
>> +struct sandbox_tee_state {
>> +       u32 session;
>> +       int num_shms;
>> +       void *ta;
>
> struct/members need comments

OK

Thanks,
Jens

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

* [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB
  2018-09-14 10:54   ` Simon Glass
@ 2018-09-25  7:34     ` Jens Wiklander
  0 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-25  7:34 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 14, 2018 at 12:54 PM, Simon Glass <sjg@chromium.org> wrote:
> On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> With CONFIG_OPTEE_TA_AVB use the trusted application AVB provided by
>> OP-TEE to manage rollback indexes and device lock status.
>
> Should this be device-lock status?

Yes, I'll fix.

>
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  common/avb_verify.c  | 118 ++++++++++++++++++++++++++++++++++++++++++-
>>  doc/README.avb2      |  13 +++++
>>  include/avb_verify.h |   4 ++
>>  3 files changed, 134 insertions(+), 1 deletion(-)
>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Thanks,
Jens

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

* [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration
  2018-09-14 10:54   ` Simon Glass
@ 2018-09-25 10:50     ` Jens Wiklander
  0 siblings, 0 replies; 35+ messages in thread
From: Jens Wiklander @ 2018-09-25 10:50 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Fri, Sep 14, 2018 at 12:54 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Jens,
>
> On 3 September 2018 at 16:47, Jens Wiklander <jens.wiklander@linaro.org> wrote:
>> With CONFIG_SANDBOX malloc a buffer in get_sector_buf() and return that
>> instead of returning CONFIG_FASTBOOT_BUF_ADDR since there's no such
>> buffer reserved.
>>
>> Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
>> ---
>>  include/avb_verify.h | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/include/avb_verify.h b/include/avb_verify.h
>> index a532a2331aea..7b95409d247e 100644
>> --- a/include/avb_verify.h
>> +++ b/include/avb_verify.h
>> @@ -76,7 +76,16 @@ static inline size_t get_sector_buf_size(void)
>>
>>  static inline void *get_sector_buf(void)
>>  {
>> +#ifdef CONFIG_SANDBOX
>> +       static void *p;
>> +
>> +       if (!p)
>> +               p = avb_malloc_(get_sector_buf_size());
>> +
>> +       return p;
>> +#else
>>         return (void *)CONFIG_FASTBOOT_BUF_ADDR;
>
> Can you not define this on sandbox? We don't want sandbox to have
> special-case code if we can avoid it.
>
> If you do define it, you should change the code to:
>
> return map_sysmem(CONFIG_..., size);
>
> which works on sandbox and other archs too.

Thanks, I'll use that.

--
Jens

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

* [U-Boot] [PATCH v3 15/20] tee: add sandbox driver
  2018-09-25  7:33     ` Jens Wiklander
@ 2018-10-02 11:22       ` Simon Glass
  0 siblings, 0 replies; 35+ messages in thread
From: Simon Glass @ 2018-10-02 11:22 UTC (permalink / raw)
  To: u-boot

Hi Jens,

On 25 September 2018 at 00:33, Jens Wiklander <jens.wiklander@linaro.org> wrote:
> Hi Simon,
>
> I have one question inline below.
>
> On Fri, Sep 14, 2018 at 12:53 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Jens,

[..]

>>> diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c
>>> new file mode 100644
>>> index 000000000000..cd073497615f
>>> --- /dev/null
>>> +++ b/drivers/tee/sandbox.c
>>> @@ -0,0 +1,299 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Copyright (C) 2018 Linaro Limited
>>> + */
>>> +#include <common.h>
>>> +#include <dm.h>
>>> +#include <sandboxtee.h>
>>
>> Could this go in asm/ ?
>
> I don't understand. What should go into asm/ and which directory is that?

I mean arch/sandbox/include/asm, if this is a file that is only used on sandbox.

Regards,
Simon

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

end of thread, other threads:[~2018-10-02 11:22 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-03 14:46 [U-Boot] [PATCH v3 00/20] AVB using OP-TEE Jens Wiklander
2018-09-03 14:46 ` [U-Boot] [PATCH v3 01/20] dm: fdt: scan for devices under /firmware too Jens Wiklander
2018-09-03 14:46 ` [U-Boot] [PATCH v3 02/20] cmd: avb read_rb: print rb_idx in hexadecimal Jens Wiklander
2018-09-03 14:46 ` [U-Boot] [PATCH v3 03/20] cmd: avb: print error message if command fails Jens Wiklander
2018-09-03 14:46 ` [U-Boot] [PATCH v3 04/20] avb_verify: bugfix avb_ops_free() skipping free Jens Wiklander
2018-09-14 10:53   ` Simon Glass
2018-09-03 14:46 ` [U-Boot] [PATCH v3 05/20] mmc: rpmb: add mmc_rpmb_route_frames() Jens Wiklander
2018-09-14 10:53   ` Simon Glass
2018-09-25  6:14     ` Jens Wiklander
2018-09-03 14:46 ` [U-Boot] [PATCH v3 06/20] Add UCLASS_TEE for Trusted Execution Environment Jens Wiklander
2018-09-03 14:46 ` [U-Boot] [PATCH v3 07/20] dt/bindings: add bindings for optee Jens Wiklander
2018-09-14 10:53   ` Simon Glass
2018-09-03 14:46 ` [U-Boot] [PATCH v3 08/20] tee: add OP-TEE driver Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 09/20] Documentation: tee uclass and op-tee driver Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 10/20] arm: dt: hikey: Add optee node Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 11/20] optee: support routing of rpmb data frames to mmc Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 12/20] tee: optee: support AVB trusted application Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 13/20] sandbox: dt: add sandbox_tee node Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 14/20] sandbox: imply CONFIG_TEE (TEE uclass) Jens Wiklander
2018-09-14 10:53   ` Simon Glass
2018-09-03 14:47 ` [U-Boot] [PATCH v3 15/20] tee: add sandbox driver Jens Wiklander
2018-09-14 10:53   ` Simon Glass
2018-09-25  7:33     ` Jens Wiklander
2018-10-02 11:22       ` Simon Glass
2018-09-03 14:47 ` [U-Boot] [PATCH v3 16/20] test: tee: test TEE uclass Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 17/20] avb_verify: support using OP-TEE TA AVB Jens Wiklander
2018-09-14 10:54   ` Simon Glass
2018-09-25  7:34     ` Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 18/20] test_avb: Update pymark.buildconfigspec information for the AVB tests Jens Wiklander
2018-09-14 10:54   ` Simon Glass
2018-09-03 14:47 ` [U-Boot] [PATCH v3 19/20] avb_verify: support sandbox configuration Jens Wiklander
2018-09-14 10:54   ` Simon Glass
2018-09-25 10:50     ` Jens Wiklander
2018-09-03 14:47 ` [U-Boot] [PATCH v3 20/20] Kconfig: sandbox: enable cmd_avb and dependencies Jens Wiklander
2018-09-14 10:54   ` Simon Glass

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.