Commit 232cfd6d9152fd2a4e7113faec51db2a9ab8c6bd

Authored by Jens Wiklander
Committed by Tom Rini
1 parent 7ab5630a42

optee: support routing of rpmb data frames to mmc

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>
Reviewed-by: Simon Glass <sjg@chromium.org>

Showing 5 changed files with 247 additions and 1 deletions Side-by-side Diff

drivers/tee/optee/Makefile
... ... @@ -2,4 +2,5 @@
2 2  
3 3 obj-y += core.o
4 4 obj-y += supplicant.o
  5 +obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
drivers/tee/optee/core.c
... ... @@ -315,6 +315,13 @@
315 315 param.a3 = res.a3;
316 316 handle_rpc(dev, &param, &page_list);
317 317 } else {
  318 + /*
  319 + * In case we've accessed RPMB to serve an RPC
  320 + * request we need to restore the previously
  321 + * selected partition as the caller may expect it
  322 + * to remain unchanged.
  323 + */
  324 + optee_suppl_rpmb_release(dev);
318 325 return call_err_to_res(res.a0);
319 326 }
320 327 }
... ... @@ -651,5 +658,6 @@
651 658 .probe = optee_probe,
652 659 .ops = &optee_ops,
653 660 .platdata_auto_alloc_size = sizeof(struct optee_pdata),
  661 + .priv_auto_alloc_size = sizeof(struct optee_private),
654 662 };
drivers/tee/optee/optee_private.h
... ... @@ -6,8 +6,61 @@
6 6 #ifndef __OPTEE_PRIVATE_H
7 7 #define __OPTEE_PRIVATE_H
8 8  
  9 +#include <tee.h>
  10 +#include <log.h>
  11 +
  12 +/**
  13 + * struct optee_private - OP-TEE driver private data
  14 + * @rpmb_mmc: mmc device for the RPMB partition
  15 + * @rpmb_dev_id: mmc device id matching @rpmb_mmc
  16 + * @rpmb_original_part: the previosly active partition on the mmc device,
  17 + * used to restore active the partition when the RPMB
  18 + * accesses are finished
  19 + */
  20 +struct optee_private {
  21 + struct mmc *rpmb_mmc;
  22 + int rpmb_dev_id;
  23 + int rpmb_original_part;
  24 +};
  25 +
  26 +struct optee_msg_arg;
  27 +
  28 +void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
  29 + void **page_list);
  30 +
  31 +#ifdef CONFIG_SUPPORT_EMMC_RPMB
  32 +/**
  33 + * optee_suppl_cmd_rpmb() - route RPMB frames to mmc
  34 + * @dev: device with the selected RPMB partition
  35 + * @arg: OP-TEE message holding the frames to transmit to the mmc
  36 + * and space for the response frames.
  37 + *
  38 + * Routes signed (MACed) RPMB frames from OP-TEE Secure OS to MMC and vice
  39 + * versa to manipulate the RPMB partition.
  40 + */
  41 +void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg);
  42 +
  43 +/**
  44 + * optee_suppl_rpmb_release() - release mmc device
  45 + * @dev: mmc device
  46 + *
  47 + * Releases the mmc device and restores the previously selected partition.
  48 + */
  49 +void optee_suppl_rpmb_release(struct udevice *dev);
  50 +#else
  51 +static inline void optee_suppl_cmd_rpmb(struct udevice *dev,
  52 + struct optee_msg_arg *arg)
  53 +{
  54 + debug("OPTEE_MSG_RPC_CMD_RPMB not implemented\n");
  55 + arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
  56 +}
  57 +
  58 +static inline void optee_suppl_rpmb_release(struct udevice *dev)
  59 +{
  60 +}
  61 +#endif
  62 +
9 63 void *optee_alloc_and_init_page_list(void *buf, ulong len, u64 *phys_buf_ptr);
10   -void optee_suppl_cmd(struct udevice *dev, void *shm, void **page_list);
11 64  
12 65 #endif /* __OPTEE_PRIVATE_H */
drivers/tee/optee/rpmb.c
  1 +// SPDX-License-Identifier: BSD-2-Clause
  2 +/*
  3 + * Copyright (c) 2018 Linaro Limited
  4 + */
  5 +
  6 +#include <common.h>
  7 +#include <dm.h>
  8 +#include <log.h>
  9 +#include <tee.h>
  10 +#include <mmc.h>
  11 +
  12 +#include "optee_msg.h"
  13 +#include "optee_private.h"
  14 +
  15 +/*
  16 + * Request and response definitions must be in sync with the secure side of
  17 + * OP-TEE.
  18 + */
  19 +
  20 +/* Request */
  21 +struct rpmb_req {
  22 + u16 cmd;
  23 +#define RPMB_CMD_DATA_REQ 0x00
  24 +#define RPMB_CMD_GET_DEV_INFO 0x01
  25 + u16 dev_id;
  26 + u16 block_count;
  27 + /* Optional data frames (rpmb_data_frame) follow */
  28 +};
  29 +
  30 +#define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))
  31 +
  32 +/* Response to device info request */
  33 +struct rpmb_dev_info {
  34 + u8 cid[16];
  35 + u8 rpmb_size_mult; /* EXT CSD-slice 168: RPMB Size */
  36 + u8 rel_wr_sec_c; /* EXT CSD-slice 222: Reliable Write Sector */
  37 + /* Count */
  38 + u8 ret_code;
  39 +#define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00
  40 +#define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01
  41 +};
  42 +
  43 +static void release_mmc(struct optee_private *priv)
  44 +{
  45 + int rc;
  46 +
  47 + if (!priv->rpmb_mmc)
  48 + return;
  49 +
  50 + rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
  51 + priv->rpmb_original_part);
  52 + if (rc)
  53 + debug("%s: blk_select_hwpart_devnum() failed: %d\n",
  54 + __func__, rc);
  55 +
  56 + priv->rpmb_mmc = NULL;
  57 +}
  58 +
  59 +static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
  60 +{
  61 + struct mmc *mmc;
  62 + int rc;
  63 +
  64 + if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
  65 + return priv->rpmb_mmc;
  66 +
  67 + release_mmc(priv);
  68 +
  69 + mmc = find_mmc_device(dev_id);
  70 + if (!mmc) {
  71 + debug("Cannot find RPMB device\n");
  72 + return NULL;
  73 + }
  74 + if (!(mmc->version & MMC_VERSION_MMC)) {
  75 + debug("Device id %d is not an eMMC device\n", dev_id);
  76 + return NULL;
  77 + }
  78 + if (mmc->version < MMC_VERSION_4_41) {
  79 + debug("Device id %d: RPMB not supported before version 4.41\n",
  80 + dev_id);
  81 + return NULL;
  82 + }
  83 +
  84 + priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
  85 +
  86 + rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
  87 + if (rc) {
  88 + debug("Device id %d: cannot select RPMB partition: %d\n",
  89 + dev_id, rc);
  90 + return NULL;
  91 + }
  92 +
  93 + priv->rpmb_mmc = mmc;
  94 + priv->rpmb_dev_id = dev_id;
  95 + return mmc;
  96 +}
  97 +
  98 +static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
  99 +{
  100 + struct mmc *mmc = find_mmc_device(dev_id);
  101 +
  102 + if (!mmc)
  103 + return TEE_ERROR_ITEM_NOT_FOUND;
  104 +
  105 + if (!mmc->ext_csd)
  106 + return TEE_ERROR_GENERIC;
  107 +
  108 + memcpy(info->cid, mmc->cid, sizeof(info->cid));
  109 + info->rel_wr_sec_c = mmc->ext_csd[222];
  110 + info->rpmb_size_mult = mmc->ext_csd[168];
  111 + info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;
  112 +
  113 + return TEE_SUCCESS;
  114 +}
  115 +
  116 +static u32 rpmb_process_request(struct optee_private *priv, void *req,
  117 + ulong req_size, void *rsp, ulong rsp_size)
  118 +{
  119 + struct rpmb_req *sreq = req;
  120 + struct mmc *mmc;
  121 +
  122 + if (req_size < sizeof(*sreq))
  123 + return TEE_ERROR_BAD_PARAMETERS;
  124 +
  125 + switch (sreq->cmd) {
  126 + case RPMB_CMD_DATA_REQ:
  127 + mmc = get_mmc(priv, sreq->dev_id);
  128 + if (!mmc)
  129 + return TEE_ERROR_ITEM_NOT_FOUND;
  130 + if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
  131 + req_size - sizeof(struct rpmb_req),
  132 + rsp, rsp_size))
  133 + return TEE_ERROR_BAD_PARAMETERS;
  134 + return TEE_SUCCESS;
  135 +
  136 + case RPMB_CMD_GET_DEV_INFO:
  137 + if (req_size != sizeof(struct rpmb_req) ||
  138 + rsp_size != sizeof(struct rpmb_dev_info)) {
  139 + debug("Invalid req/rsp size\n");
  140 + return TEE_ERROR_BAD_PARAMETERS;
  141 + }
  142 + return rpmb_get_dev_info(sreq->dev_id, rsp);
  143 +
  144 + default:
  145 + debug("Unsupported RPMB command: %d\n", sreq->cmd);
  146 + return TEE_ERROR_BAD_PARAMETERS;
  147 + }
  148 +}
  149 +
  150 +void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
  151 +{
  152 + struct tee_shm *req_shm;
  153 + struct tee_shm *rsp_shm;
  154 + void *req_buf;
  155 + void *rsp_buf;
  156 + ulong req_size;
  157 + ulong rsp_size;
  158 +
  159 + if (arg->num_params != 2 ||
  160 + arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
  161 + arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
  162 + arg->ret = TEE_ERROR_BAD_PARAMETERS;
  163 + return;
  164 + }
  165 +
  166 + req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
  167 + req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
  168 + req_size = arg->params[0].u.rmem.size;
  169 +
  170 + rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
  171 + rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
  172 + rsp_size = arg->params[1].u.rmem.size;
  173 +
  174 + arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
  175 + rsp_buf, rsp_size);
  176 +}
  177 +
  178 +void optee_suppl_rpmb_release(struct udevice *dev)
  179 +{
  180 + release_mmc(dev_get_priv(dev));
  181 +}
drivers/tee/optee/supplicant.c
... ... @@ -85,6 +85,9 @@
85 85 debug("OPTEE_MSG_RPC_CMD_FS not implemented\n");
86 86 arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
87 87 break;
  88 + case OPTEE_MSG_RPC_CMD_RPMB:
  89 + optee_suppl_cmd_rpmb(dev, arg);
  90 + break;
88 91 default:
89 92 arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
90 93 }