xref: /openbmc/u-boot/drivers/tee/optee/rpmb.c (revision 232cfd6d9152fd2a4e7113faec51db2a9ab8c6bd)
1*232cfd6dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*232cfd6dSJens Wiklander /*
3*232cfd6dSJens Wiklander  * Copyright (c) 2018 Linaro Limited
4*232cfd6dSJens Wiklander  */
5*232cfd6dSJens Wiklander 
6*232cfd6dSJens Wiklander #include <common.h>
7*232cfd6dSJens Wiklander #include <dm.h>
8*232cfd6dSJens Wiklander #include <log.h>
9*232cfd6dSJens Wiklander #include <tee.h>
10*232cfd6dSJens Wiklander #include <mmc.h>
11*232cfd6dSJens Wiklander 
12*232cfd6dSJens Wiklander #include "optee_msg.h"
13*232cfd6dSJens Wiklander #include "optee_private.h"
14*232cfd6dSJens Wiklander 
15*232cfd6dSJens Wiklander /*
16*232cfd6dSJens Wiklander  * Request and response definitions must be in sync with the secure side of
17*232cfd6dSJens Wiklander  * OP-TEE.
18*232cfd6dSJens Wiklander  */
19*232cfd6dSJens Wiklander 
20*232cfd6dSJens Wiklander /* Request */
21*232cfd6dSJens Wiklander struct rpmb_req {
22*232cfd6dSJens Wiklander 	u16 cmd;
23*232cfd6dSJens Wiklander #define RPMB_CMD_DATA_REQ      0x00
24*232cfd6dSJens Wiklander #define RPMB_CMD_GET_DEV_INFO  0x01
25*232cfd6dSJens Wiklander 	u16 dev_id;
26*232cfd6dSJens Wiklander 	u16 block_count;
27*232cfd6dSJens Wiklander 	/* Optional data frames (rpmb_data_frame) follow */
28*232cfd6dSJens Wiklander };
29*232cfd6dSJens Wiklander 
30*232cfd6dSJens Wiklander #define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1))
31*232cfd6dSJens Wiklander 
32*232cfd6dSJens Wiklander /* Response to device info request */
33*232cfd6dSJens Wiklander struct rpmb_dev_info {
34*232cfd6dSJens Wiklander 	u8 cid[16];
35*232cfd6dSJens Wiklander 	u8 rpmb_size_mult;	/* EXT CSD-slice 168: RPMB Size */
36*232cfd6dSJens Wiklander 	u8 rel_wr_sec_c;	/* EXT CSD-slice 222: Reliable Write Sector */
37*232cfd6dSJens Wiklander 				/*                    Count */
38*232cfd6dSJens Wiklander 	u8 ret_code;
39*232cfd6dSJens Wiklander #define RPMB_CMD_GET_DEV_INFO_RET_OK     0x00
40*232cfd6dSJens Wiklander #define RPMB_CMD_GET_DEV_INFO_RET_ERROR  0x01
41*232cfd6dSJens Wiklander };
42*232cfd6dSJens Wiklander 
release_mmc(struct optee_private * priv)43*232cfd6dSJens Wiklander static void release_mmc(struct optee_private *priv)
44*232cfd6dSJens Wiklander {
45*232cfd6dSJens Wiklander 	int rc;
46*232cfd6dSJens Wiklander 
47*232cfd6dSJens Wiklander 	if (!priv->rpmb_mmc)
48*232cfd6dSJens Wiklander 		return;
49*232cfd6dSJens Wiklander 
50*232cfd6dSJens Wiklander 	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
51*232cfd6dSJens Wiklander 				      priv->rpmb_original_part);
52*232cfd6dSJens Wiklander 	if (rc)
53*232cfd6dSJens Wiklander 		debug("%s: blk_select_hwpart_devnum() failed: %d\n",
54*232cfd6dSJens Wiklander 		      __func__, rc);
55*232cfd6dSJens Wiklander 
56*232cfd6dSJens Wiklander 	priv->rpmb_mmc = NULL;
57*232cfd6dSJens Wiklander }
58*232cfd6dSJens Wiklander 
get_mmc(struct optee_private * priv,int dev_id)59*232cfd6dSJens Wiklander static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
60*232cfd6dSJens Wiklander {
61*232cfd6dSJens Wiklander 	struct mmc *mmc;
62*232cfd6dSJens Wiklander 	int rc;
63*232cfd6dSJens Wiklander 
64*232cfd6dSJens Wiklander 	if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
65*232cfd6dSJens Wiklander 		return priv->rpmb_mmc;
66*232cfd6dSJens Wiklander 
67*232cfd6dSJens Wiklander 	release_mmc(priv);
68*232cfd6dSJens Wiklander 
69*232cfd6dSJens Wiklander 	mmc = find_mmc_device(dev_id);
70*232cfd6dSJens Wiklander 	if (!mmc) {
71*232cfd6dSJens Wiklander 		debug("Cannot find RPMB device\n");
72*232cfd6dSJens Wiklander 		return NULL;
73*232cfd6dSJens Wiklander 	}
74*232cfd6dSJens Wiklander 	if (!(mmc->version & MMC_VERSION_MMC)) {
75*232cfd6dSJens Wiklander 		debug("Device id %d is not an eMMC device\n", dev_id);
76*232cfd6dSJens Wiklander 		return NULL;
77*232cfd6dSJens Wiklander 	}
78*232cfd6dSJens Wiklander 	if (mmc->version < MMC_VERSION_4_41) {
79*232cfd6dSJens Wiklander 		debug("Device id %d: RPMB not supported before version 4.41\n",
80*232cfd6dSJens Wiklander 		      dev_id);
81*232cfd6dSJens Wiklander 		return NULL;
82*232cfd6dSJens Wiklander 	}
83*232cfd6dSJens Wiklander 
84*232cfd6dSJens Wiklander 	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
85*232cfd6dSJens Wiklander 
86*232cfd6dSJens Wiklander 	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
87*232cfd6dSJens Wiklander 	if (rc) {
88*232cfd6dSJens Wiklander 		debug("Device id %d: cannot select RPMB partition: %d\n",
89*232cfd6dSJens Wiklander 		      dev_id, rc);
90*232cfd6dSJens Wiklander 		return NULL;
91*232cfd6dSJens Wiklander 	}
92*232cfd6dSJens Wiklander 
93*232cfd6dSJens Wiklander 	priv->rpmb_mmc = mmc;
94*232cfd6dSJens Wiklander 	priv->rpmb_dev_id = dev_id;
95*232cfd6dSJens Wiklander 	return mmc;
96*232cfd6dSJens Wiklander }
97*232cfd6dSJens Wiklander 
rpmb_get_dev_info(u16 dev_id,struct rpmb_dev_info * info)98*232cfd6dSJens Wiklander static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
99*232cfd6dSJens Wiklander {
100*232cfd6dSJens Wiklander 	struct mmc *mmc = find_mmc_device(dev_id);
101*232cfd6dSJens Wiklander 
102*232cfd6dSJens Wiklander 	if (!mmc)
103*232cfd6dSJens Wiklander 		return TEE_ERROR_ITEM_NOT_FOUND;
104*232cfd6dSJens Wiklander 
105*232cfd6dSJens Wiklander 	if (!mmc->ext_csd)
106*232cfd6dSJens Wiklander 		return TEE_ERROR_GENERIC;
107*232cfd6dSJens Wiklander 
108*232cfd6dSJens Wiklander 	memcpy(info->cid, mmc->cid, sizeof(info->cid));
109*232cfd6dSJens Wiklander 	info->rel_wr_sec_c = mmc->ext_csd[222];
110*232cfd6dSJens Wiklander 	info->rpmb_size_mult = mmc->ext_csd[168];
111*232cfd6dSJens Wiklander 	info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK;
112*232cfd6dSJens Wiklander 
113*232cfd6dSJens Wiklander 	return TEE_SUCCESS;
114*232cfd6dSJens Wiklander }
115*232cfd6dSJens Wiklander 
rpmb_process_request(struct optee_private * priv,void * req,ulong req_size,void * rsp,ulong rsp_size)116*232cfd6dSJens Wiklander static u32 rpmb_process_request(struct optee_private *priv, void *req,
117*232cfd6dSJens Wiklander 				ulong req_size, void *rsp, ulong rsp_size)
118*232cfd6dSJens Wiklander {
119*232cfd6dSJens Wiklander 	struct rpmb_req *sreq = req;
120*232cfd6dSJens Wiklander 	struct mmc *mmc;
121*232cfd6dSJens Wiklander 
122*232cfd6dSJens Wiklander 	if (req_size < sizeof(*sreq))
123*232cfd6dSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
124*232cfd6dSJens Wiklander 
125*232cfd6dSJens Wiklander 	switch (sreq->cmd) {
126*232cfd6dSJens Wiklander 	case RPMB_CMD_DATA_REQ:
127*232cfd6dSJens Wiklander 		mmc = get_mmc(priv, sreq->dev_id);
128*232cfd6dSJens Wiklander 		if (!mmc)
129*232cfd6dSJens Wiklander 			return TEE_ERROR_ITEM_NOT_FOUND;
130*232cfd6dSJens Wiklander 		if (mmc_rpmb_route_frames(mmc, RPMB_REQ_DATA(req),
131*232cfd6dSJens Wiklander 					  req_size - sizeof(struct rpmb_req),
132*232cfd6dSJens Wiklander 					  rsp, rsp_size))
133*232cfd6dSJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
134*232cfd6dSJens Wiklander 		return TEE_SUCCESS;
135*232cfd6dSJens Wiklander 
136*232cfd6dSJens Wiklander 	case RPMB_CMD_GET_DEV_INFO:
137*232cfd6dSJens Wiklander 		if (req_size != sizeof(struct rpmb_req) ||
138*232cfd6dSJens Wiklander 		    rsp_size != sizeof(struct rpmb_dev_info)) {
139*232cfd6dSJens Wiklander 			debug("Invalid req/rsp size\n");
140*232cfd6dSJens Wiklander 			return TEE_ERROR_BAD_PARAMETERS;
141*232cfd6dSJens Wiklander 		}
142*232cfd6dSJens Wiklander 		return rpmb_get_dev_info(sreq->dev_id, rsp);
143*232cfd6dSJens Wiklander 
144*232cfd6dSJens Wiklander 	default:
145*232cfd6dSJens Wiklander 		debug("Unsupported RPMB command: %d\n", sreq->cmd);
146*232cfd6dSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
147*232cfd6dSJens Wiklander 	}
148*232cfd6dSJens Wiklander }
149*232cfd6dSJens Wiklander 
optee_suppl_cmd_rpmb(struct udevice * dev,struct optee_msg_arg * arg)150*232cfd6dSJens Wiklander void optee_suppl_cmd_rpmb(struct udevice *dev, struct optee_msg_arg *arg)
151*232cfd6dSJens Wiklander {
152*232cfd6dSJens Wiklander 	struct tee_shm *req_shm;
153*232cfd6dSJens Wiklander 	struct tee_shm *rsp_shm;
154*232cfd6dSJens Wiklander 	void *req_buf;
155*232cfd6dSJens Wiklander 	void *rsp_buf;
156*232cfd6dSJens Wiklander 	ulong req_size;
157*232cfd6dSJens Wiklander 	ulong rsp_size;
158*232cfd6dSJens Wiklander 
159*232cfd6dSJens Wiklander 	if (arg->num_params != 2 ||
160*232cfd6dSJens Wiklander 	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
161*232cfd6dSJens Wiklander 	    arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
162*232cfd6dSJens Wiklander 		arg->ret = TEE_ERROR_BAD_PARAMETERS;
163*232cfd6dSJens Wiklander 		return;
164*232cfd6dSJens Wiklander 	}
165*232cfd6dSJens Wiklander 
166*232cfd6dSJens Wiklander 	req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
167*232cfd6dSJens Wiklander 	req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
168*232cfd6dSJens Wiklander 	req_size = arg->params[0].u.rmem.size;
169*232cfd6dSJens Wiklander 
170*232cfd6dSJens Wiklander 	rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
171*232cfd6dSJens Wiklander 	rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
172*232cfd6dSJens Wiklander 	rsp_size = arg->params[1].u.rmem.size;
173*232cfd6dSJens Wiklander 
174*232cfd6dSJens Wiklander 	arg->ret = rpmb_process_request(dev_get_priv(dev), req_buf, req_size,
175*232cfd6dSJens Wiklander 					rsp_buf, rsp_size);
176*232cfd6dSJens Wiklander }
177*232cfd6dSJens Wiklander 
optee_suppl_rpmb_release(struct udevice * dev)178*232cfd6dSJens Wiklander void optee_suppl_rpmb_release(struct udevice *dev)
179*232cfd6dSJens Wiklander {
180*232cfd6dSJens Wiklander 	release_mmc(dev_get_priv(dev));
181*232cfd6dSJens Wiklander }
182