1 // SPDX-License-Identifier: BSD-2-Clause
3 * Copyright (c) 2018 Linaro Limited
11 #include <dm/device_compat.h>
13 #include "optee_msg.h"
14 #include "optee_private.h"
17 * Request and response definitions must be in sync with the secure side of
24 #define RPMB_CMD_DATA_REQ 0x00
25 #define RPMB_CMD_GET_DEV_INFO 0x01
28 /* Optional data frames (rpmb_data_frame) follow */
31 #define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))
33 /* Response to device info request */
34 struct rpmb_dev_info {
36 u8 rpmb_size_mult; /* EXT CSD-slice 168: RPMB Size */
37 u8 rel_wr_sec_c; /* EXT CSD-slice 222: Reliable Write Sector */
40 #define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00
41 #define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01
44 static void release_mmc(struct optee_private *priv)
51 rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
52 priv->rpmb_original_part);
54 debug("%s: blk_select_hwpart_devnum() failed: %d\n",
57 priv->rpmb_mmc = NULL;
60 static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
65 if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
66 return priv->rpmb_mmc;
70 mmc = find_mmc_device(dev_id);
72 debug("Cannot find RPMB device\n");
75 if (!(mmc->version & MMC_VERSION_MMC)) {
76 debug("Device id %d is not an eMMC device\n", dev_id);
79 if (mmc->version < MMC_VERSION_4_41) {
80 debug("Device id %d: RPMB not supported before version 4.41\n",
85 priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
87 rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
89 debug("Device id %d: cannot select RPMB partition: %d\n",
95 priv->rpmb_dev_id = dev_id;
99 static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
101 struct mmc *mmc = find_mmc_device(dev_id);
105 return TEE_ERROR_ITEM_NOT_FOUND;
108 return TEE_ERROR_GENERIC;
110 for (i = 0; i < ARRAY_SIZE(mmc->cid); i++)
111 ((u32 *) info->cid)[i] = cpu_to_be32(mmc->cid[i]);
113 info->rel_wr_sec_c = mmc->ext_csd[222];
114 info->rpmb_size_mult = mmc->ext_csd[168];
115 info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;
120 static u32 rpmb_process_request(struct optee_private *priv, void *req,
121 ulong req_size, void *rsp, ulong rsp_size)
123 struct rpmb_req *sreq = req;
126 if (req_size < sizeof(*sreq))
127 return TEE_ERROR_BAD_PARAMETERS;
130 case RPMB_CMD_DATA_REQ:
131 mmc = get_mmc(priv, sreq->dev_id);
133 return TEE_ERROR_ITEM_NOT_FOUND;
134 if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
135 req_size - sizeof(struct rpmb_req),
137 return TEE_ERROR_BAD_PARAMETERS;
140 case RPMB_CMD_GET_DEV_INFO:
141 if (req_size != sizeof(struct rpmb_req) ||
142 rsp_size != sizeof(struct rpmb_dev_info)) {
143 debug("Invalid req/rsp size\n");
144 return TEE_ERROR_BAD_PARAMETERS;
146 return rpmb_get_dev_info(sreq->dev_id, rsp);
149 debug("Unsupported RPMB command: %d\n", sreq->cmd);
150 return TEE_ERROR_BAD_PARAMETERS;
154 void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
156 struct tee_shm *req_shm;
157 struct tee_shm *rsp_shm;
163 if (arg->num_params != 2 ||
164 arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
165 arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
166 arg->ret = TEE_ERROR_BAD_PARAMETERS;
170 req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
171 req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
172 req_size = arg->params[0].u.rmem.size;
174 rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
175 rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
176 rsp_size = arg->params[1].u.rmem.size;
178 arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
182 void optee_suppl_rpmb_release(struct udevice *dev)
184 release_mmc(dev_get_priv(dev));