aboutsummaryrefslogtreecommitdiffstats
path: root/meta-agl-bsp/meta-rcar-gen3/recipes-bsp/optee/optee-client/0001-tee-supplicant-use-MMC_IOC_MULTI_CMD-for-RPMB-access.patch
blob: fddc7fc133fd159af8779ace16bc543e3c5890bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
From 04a72e88f768722edff453694e70535d36a8b1b4 Mon Sep 17 00:00:00 2001
From: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
Date: Mon, 1 Apr 2019 13:10:57 +0900
Subject: [PATCH] tee-supplicant: use MMC_IOC_MULTI_CMD for RPMB access

To access RPMB, host should switch to RPMB partition.
And in RPMB partition, host should finish RPMB sequence.

In case of using MMC_IOC_CMD as RPMB ioctl, eMMC driver switches
partition to user data area between WRITE command and READ command.
This may cause General failure.
In case of MMC_IOC_MULTI_CMD, eMMC driver keeps RPMB partition.

This patch changes RPMB ioctl from MMC_IOC_CMD into MMC_IOC_MULTI_CMD
and changes ioctl parameters according to mmc utils.

Signed-off-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
---
 tee-supplicant/src/rpmb.c | 120 +++++++++++++++++++++++-----------------------
 1 file changed, 61 insertions(+), 59 deletions(-)

diff --git a/tee-supplicant/src/rpmb.c b/tee-supplicant/src/rpmb.c
index cac9932..29da690 100644
--- a/tee-supplicant/src/rpmb.c
+++ b/tee-supplicant/src/rpmb.c
@@ -114,6 +114,7 @@ static pthread_mutex_t rpmb_mutex = PTHREAD_MUTEX_INITIALIZER;
  */
 
 #define MMC_BLOCK_MAJOR	179
+#define RPMB_MULTI_CMD_MAX_CMDS 3
 
 /* mmc_ioc_cmd.opcode */
 #define MMC_SEND_EXT_CSD		 8
@@ -130,6 +131,9 @@ static pthread_mutex_t rpmb_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 #define MMC_CMD_ADTC	(1 << 5)	/* Addressed data transfer command */
 
+#define MMC_RSP_SPI_S1	(1 << 7)	/* one status byte */
+#define MMC_RSP_SPI_R1	(MMC_RSP_SPI_S1)
+
 /* mmc_ioc_cmd.write_flag */
 #define MMC_CMD23_ARG_REL_WR	(1 << 31) /* CMD23 reliable write */
 
@@ -610,26 +614,38 @@ static uint32_t read_ext_csd(int fd, uint8_t *ext_csd)
 	return TEEC_SUCCESS;
 }
 
+static inline void set_single_cmd(struct mmc_ioc_cmd *ioc, __u32 opcode,
+				  int write_flag, unsigned int blocks)
+{
+	ioc->opcode = opcode;
+	ioc->write_flag = write_flag;
+	ioc->arg = 0x0;
+	ioc->blksz = 512;
+	ioc->blocks = blocks;
+	ioc->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+}
+
 static uint32_t rpmb_data_req(int fd, struct rpmb_data_frame *req_frm,
 			      size_t req_nfrm, struct rpmb_data_frame *rsp_frm,
 			      size_t rsp_nfrm)
 {
-	int st;
+	int err;
 	size_t i;
 	uint16_t msg_type = ntohs(req_frm->msg_type);
-	struct mmc_ioc_cmd cmd;
+	struct mmc_ioc_cmd *ioc;
+	struct mmc_ioc_multi_cmd *mioc;
+	struct rpmb_data_frame frame_status = {0};
 
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.blksz = 512;
-	cmd.blocks = req_nfrm;
-	cmd.data_ptr = (uintptr_t)req_frm;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-	cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
-	cmd.write_flag = 1;
+	mioc = (struct mmc_ioc_multi_cmd *)
+		malloc(sizeof(struct mmc_ioc_multi_cmd) +
+		       RPMB_MULTI_CMD_MAX_CMDS * sizeof(struct mmc_ioc_cmd));
+	if (!mioc)
+		return -ENOMEM;
 
 	for (i = 1; i < req_nfrm; i++) {
 		if (req_frm[i].msg_type != msg_type) {
 			EMSG("All request frames shall be of the same type");
+			free(mioc);
 			return TEEC_ERROR_BAD_PARAMETERS;
 		}
 	}
@@ -642,77 +658,63 @@ static uint32_t rpmb_data_req(int fd, struct rpmb_data_frame *req_frm,
 	case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE:
 		if (rsp_nfrm != 1) {
 			EMSG("Expected only one response frame");
+			free(mioc);
 			return TEEC_ERROR_BAD_PARAMETERS;
 		}
 
-		/* Send write request frame(s) */
-		cmd.write_flag |= MMC_CMD23_ARG_REL_WR;
-		/*
-		 * Black magic: tested on a HiKey board with a HardKernel eMMC
-		 * module. When postsleep values are zero, the kernel logs
-		 * random errors: "mmc_blk_ioctl_cmd: Card Status=0x00000E00"
-		 * and ioctl() fails.
-		 */
-		cmd.postsleep_min_us = 20000;
-		cmd.postsleep_max_us = 50000;
-		st = IOCTL(fd, MMC_IOC_CMD, &cmd);
-		if (st < 0)
-			return TEEC_ERROR_GENERIC;
-		cmd.postsleep_min_us = 0;
-		cmd.postsleep_max_us = 0;
-
-		/* Send result request frame */
-		memset(rsp_frm, 0, 1);
-		rsp_frm->msg_type = htons(RPMB_MSG_TYPE_REQ_RESULT_READ);
-		cmd.data_ptr = (uintptr_t)rsp_frm;
-		cmd.write_flag &= ~MMC_CMD23_ARG_REL_WR;
-		st = IOCTL(fd, MMC_IOC_CMD, &cmd);
-		if (st < 0)
-			return TEEC_ERROR_GENERIC;
-
-		/* Read response frame */
-		cmd.opcode = MMC_READ_MULTIPLE_BLOCK;
-		cmd.write_flag = 0;
-		cmd.blocks = rsp_nfrm;
-		st = IOCTL(fd, MMC_IOC_CMD, &cmd);
-		if (st < 0)
-			return TEEC_ERROR_GENERIC;
+		mioc->num_of_cmds = 3;
+
+		/* Write request */
+		ioc = &mioc->cmds[0];
+		set_single_cmd(ioc, MMC_WRITE_MULTIPLE_BLOCK, (1 << 31) | 1, 1);
+		mmc_ioc_cmd_set_data((*ioc), req_frm);
+
+		/* Result request */
+		ioc = &mioc->cmds[1];
+		frame_status.msg_type = htobe16(RPMB_MSG_TYPE_REQ_RESULT_READ);
+		set_single_cmd(ioc, MMC_WRITE_MULTIPLE_BLOCK, 1, 1);
+		mmc_ioc_cmd_set_data((*ioc), &frame_status);
+
+		/* Get response */
+		ioc = &mioc->cmds[2];
+		set_single_cmd(ioc, MMC_READ_MULTIPLE_BLOCK, 0, 1);
+		mmc_ioc_cmd_set_data((*ioc), rsp_frm);
+
 		break;
 
 	case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ:
 		if (rsp_nfrm != 1) {
 			EMSG("Expected only one response frame");
+			free(mioc);
 			return TEEC_ERROR_BAD_PARAMETERS;
 		}
 
 		/* Fall through */
 	case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ:
-		if (req_nfrm != 1) {
-			EMSG("Expected only one request frame");
-			return TEEC_ERROR_BAD_PARAMETERS;
-		}
+		mioc->num_of_cmds = 2;
+
+		/* Read request */
+		ioc = &mioc->cmds[0];
+		set_single_cmd(ioc, MMC_WRITE_MULTIPLE_BLOCK, 1, 1);
+		mmc_ioc_cmd_set_data((*ioc), req_frm);
+
+		/* Get response */
+		ioc = &mioc->cmds[1];
+		set_single_cmd(ioc, MMC_READ_MULTIPLE_BLOCK, 0, rsp_nfrm);
+		mmc_ioc_cmd_set_data((*ioc), rsp_frm);
 
-		/* Send request frame */
-		st = IOCTL(fd, MMC_IOC_CMD, &cmd);
-		if (st < 0)
-			return TEEC_ERROR_GENERIC;
-
-		/* Read response frames */
-		cmd.data_ptr = (uintptr_t)rsp_frm;
-		cmd.opcode = MMC_READ_MULTIPLE_BLOCK;
-		cmd.write_flag = 0;
-		cmd.blocks = rsp_nfrm;
-		st = IOCTL(fd, MMC_IOC_CMD, &cmd);
-		if (st < 0)
-			return TEEC_ERROR_GENERIC;
 		break;
 
 	default:
 		EMSG("Unsupported message type: %d", msg_type);
+		free(mioc);
 		return TEEC_ERROR_GENERIC;
 	}
 
-	return TEEC_SUCCESS;
+	err = ioctl(fd, MMC_IOC_MULTI_CMD, mioc);
+
+	free(mioc);
+	return err;
 }
 
 static uint32_t rpmb_get_dev_info(uint16_t dev_id, struct rpmb_dev_info *info)
-- 
2.7.4