* [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 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 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 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 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 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(¶m->a1, ¶m->a2,
+ virt_to_phys(shm->addr));
+ /* "cookie" */
+ reg_pair_from_64(¶m->a4, ¶m->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(¶m.a1, ¶m.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, ¶m, &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, ¶m, &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 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 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 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
* [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, ¶m) || 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, ®_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, ¶m);
+ 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 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 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 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 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 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 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