1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Rockchip UFS Host Controller driver
4 *
5 * Copyright (C) 2024 Rockchip Electronics Co.Ltd.
6 */
7
8 #include <command.h>
9 #include <charset.h>
10 #include <common.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <dm/lists.h>
14 #include <dm/device-internal.h>
15 #include <malloc.h>
16 #include <hexdump.h>
17 #include <scsi.h>
18 #include <asm/io.h>
19 #include <asm/dma-mapping.h>
20 #include <linux/bitops.h>
21 #include <linux/delay.h>
22
23 #include "ufs.h"
24 #include "ufs-rockchip-rpmb.h"
25 #include <u-boot/sha256.h>
26
27 extern int ufs_send_scsi_cmd(struct ufs_hba *hba, struct scsi_cmd *pccb);
28
29 #define UFS_OP_SECURITY_PROTOCOL_IN 0xA2
30 #define UFS_OP_SECURITY_PROTOCOL_OUT 0xB5
31 #define UFS_OP_TST_U_RDY 0x00
32 #define UFS_RPMB_KEY_SZ 32
33 #define SHA256_BLOCK_SIZE 64
34
35 static struct ufs_hba *rpmb_hba;
36
37 struct lu_info_tbl {
38 int lu_index;
39 uint32_t log2blksz;
40 uint64_t blkcnt;
41 };
42
43 struct lu_info_tbl rpmb_lu_info = {0};
44 static struct scsi_cmd tempccb; /* temporary scsi command buffer */
45
u16_to_bytes(uint16_t u16,uint8_t * bytes)46 static void u16_to_bytes(uint16_t u16, uint8_t *bytes)
47 {
48 *bytes = (uint8_t) (u16 >> 8);
49 *(bytes + 1) = (uint8_t) u16;
50 }
51
bytes_to_u16(uint8_t * bytes,uint16_t * u16)52 static void bytes_to_u16(uint8_t *bytes, uint16_t *u16)
53 {
54 *u16 = (uint16_t) ((*bytes << 8) + *(bytes + 1));
55 }
56
bytes_to_u32(uint8_t * bytes,uint32_t * u32)57 static void bytes_to_u32(uint8_t *bytes, uint32_t *u32)
58 {
59 *u32 = (uint32_t) ((*(bytes) << 24) +
60 (*(bytes + 1) << 16) +
61 (*(bytes + 2) << 8) + (*(bytes + 3)));
62 }
63
u32_to_bytes(uint32_t u32,uint8_t * bytes)64 static void u32_to_bytes(uint32_t u32, uint8_t *bytes)
65 {
66 *bytes = (uint8_t) (u32 >> 24);
67 *(bytes + 1) = (uint8_t) (u32 >> 16);
68 *(bytes + 2) = (uint8_t) (u32 >> 8);
69 *(bytes + 3) = (uint8_t) u32;
70 }
71
hba_test(struct ufs_hba * hba)72 static int hba_test(struct ufs_hba *hba)
73 {
74 if (!hba) {
75 printf("No UFS device!\n");
76 return -ENODEV;
77 }
78
79 return 0;
80 }
81
scsi_secproc_in(struct scsi_cmd * pccb,uint32_t lba,uint32_t size)82 static void scsi_secproc_in(struct scsi_cmd *pccb, uint32_t lba, uint32_t size)
83 {
84 pccb->cmd[0] = UFS_OP_SECURITY_PROTOCOL_IN; /* 0: opcode */
85 pccb->cmd[1] = 0xEC; /* 1: security protocal */
86 pccb->cmd[2] = 0; /* 2: specific */
87 pccb->cmd[3] = 0x1; /* 3: specific */
88 pccb->cmd[4] = 0; /* 4: reserved */
89 pccb->cmd[5] = 0; /* 5: reserved */
90 pccb->cmd[6] = (uint8_t)((size >> 24) & 0xff); /* 6: MSB, shift 24 */
91 pccb->cmd[7] = (uint8_t)((size >> 16) & 0xff); /* 7: MSB, shift 16 */
92 pccb->cmd[8] = (uint8_t)((size >> 8) & 0xff); /* 8: LSB, shift 8 */
93 pccb->cmd[9] = (uint8_t)(size & 0xff); /* 9: LSB */
94 pccb->cmd[10] = 0; /* 10: reserved */
95 pccb->cmd[11] = 0; /* 11: control */
96
97 pccb->cmdlen = 12;
98 }
99
scsi_secproc_out(struct scsi_cmd * pccb,uint32_t lba,uint32_t size)100 static void scsi_secproc_out(struct scsi_cmd *pccb, uint32_t lba, uint32_t size)
101 {
102 pccb->cmd[0] = UFS_OP_SECURITY_PROTOCOL_OUT; /* 0: opcode */
103 pccb->cmd[1] = 0xEC; /* 1: security protocal */
104 pccb->cmd[2] = 0; /* 2: specific */
105 pccb->cmd[3] = 0x1; /* 3: specific */
106 pccb->cmd[4] = 0; /* 4: reserved */
107 pccb->cmd[5] = 0; /* 5: reserved */
108 pccb->cmd[6] = (uint8_t)((size >> 24) & 0xff); /* 6: MSB, shift 24 */
109 pccb->cmd[7] = (uint8_t)((size >> 16) & 0xff); /* 7: MSB, shift 16 */
110 pccb->cmd[8] = (uint8_t)((size >> 8) & 0xff); /* 8: LSB, shift 8 */
111 pccb->cmd[9] = (uint8_t)(size & 0xff); /* 9: LSB */
112 pccb->cmd[10] = 0; /* 10: reserved */
113 pccb->cmd[11] = 0; /* 11: control */
114
115 pccb->cmdlen = 12;
116 }
117
scsi_test_unit_ready(struct scsi_cmd * pccb)118 static void scsi_test_unit_ready(struct scsi_cmd *pccb)
119 {
120 pccb->cmd[0] = UFS_OP_TST_U_RDY;
121 pccb->cmd[1] = pccb->lun << 5;
122 pccb->cmd[2] = 0;
123 pccb->cmd[3] = 0;
124 pccb->cmd[4] = 0;
125 pccb->cmd[5] = 0;
126 pccb->cmdlen = 6;
127 }
128
rpmb_send_scsi_cmd(struct ufs_hba * hba,uint32_t opcode,int dma_dir,int lun,void * buf_addr,lbaint_t start,lbaint_t blkcnt)129 static int rpmb_send_scsi_cmd(struct ufs_hba *hba, uint32_t opcode, int dma_dir, int lun,
130 void *buf_addr, lbaint_t start, lbaint_t blkcnt)
131 {
132 struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
133
134 pccb->lun = lun;
135 pccb->pdata = buf_addr;
136 pccb->dma_dir = dma_dir;
137 pccb->datalen = blkcnt * sizeof(struct rpmb_data_frame);
138
139 if (opcode == UFS_OP_SECURITY_PROTOCOL_OUT) {
140 scsi_secproc_out(pccb, start, pccb->datalen);
141 pccb->cmdlen = 12;
142 } else if (opcode == UFS_OP_SECURITY_PROTOCOL_IN) {
143 scsi_secproc_in(pccb, start, pccb->datalen);
144 pccb->cmdlen = 12;
145 } else if (opcode == UFS_OP_TST_U_RDY) {
146 scsi_test_unit_ready(pccb);
147 } else {
148 return -EINVAL;
149 }
150
151 return ufs_send_scsi_cmd(hba, pccb);
152 }
153
ufs_rpmb_hmac(unsigned char * key,struct rpmb_data_frame * frames_in,ssize_t blocks_cnt,unsigned char * output)154 static void ufs_rpmb_hmac(unsigned char *key, struct rpmb_data_frame *frames_in, ssize_t blocks_cnt,
155 unsigned char *output)
156 {
157 sha256_context ctx;
158 int i;
159 unsigned char k_ipad[SHA256_BLOCK_SIZE];
160 unsigned char k_opad[SHA256_BLOCK_SIZE];
161
162 sha256_starts(&ctx);
163
164 /* According to RFC 4634, the HMAC transform looks like:
165 SHA(K XOR opad, SHA(K XOR ipad, text))
166
167 where K is an n byte key.
168 ipad is the byte 0x36 repeated blocksize times
169 opad is the byte 0x5c repeated blocksize times
170 and text is the data being protected.
171 */
172
173 for (i = 0; i < UFS_RPMB_KEY_SZ; i++) {
174 k_ipad[i] = key[i] ^ 0x36;
175 k_opad[i] = key[i] ^ 0x5c;
176 }
177 /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
178 for ( ; i < SHA256_BLOCK_SIZE; i++) {
179 k_ipad[i] = 0x36;
180 k_opad[i] = 0x5c;
181 }
182 sha256_update(&ctx, k_ipad, SHA256_BLOCK_SIZE);
183
184 for (i = 0; i < blocks_cnt; i++)
185 sha256_update(&ctx, frames_in[i].data, RPMB_DATA_HAM_SIZE);
186
187 sha256_finish(&ctx, output);
188
189 /* Init context for second pass */
190 sha256_starts(&ctx);
191
192 /* start with outer pad */
193 sha256_update(&ctx, k_opad, SHA256_BLOCK_SIZE);
194
195 /* then results of 1st hash */
196 sha256_update(&ctx, output, UFS_RPMB_KEY_SZ);
197
198 /* finish up 2nd pass */
199 sha256_finish(&ctx, output);
200 }
201
prepare_rpmb_lu(void)202 int prepare_rpmb_lu(void)
203 {
204 struct ufs_rpmb_unit_desc_tbl rpmb_unit_desc;
205 uint64_t block_count = 0;
206 int ret = 0;
207
208 ret = hba_test(rpmb_hba);
209 if (ret)
210 return ret;
211
212 ret = ufshcd_read_desc_param(rpmb_hba, QUERY_DESC_IDN_UNIT, 0xc4, 0, (u8 *)&rpmb_unit_desc,
213 QUERY_DESC_UNIT_DEF_SIZE);
214 if (ret) {
215 dev_err(hba->dev, "%s: Failed reading RPMB Desc. err = %d\n", __func__, ret);
216 return ret;
217 }
218
219 block_count = be64_to_cpu(rpmb_unit_desc.qLogicalBlockCount);
220 if (block_count) {
221 rpmb_lu_info.lu_index = 0xc4;
222 rpmb_lu_info.blkcnt = block_count;
223 rpmb_lu_info.log2blksz = rpmb_unit_desc.bLogicalBlockSize;
224 /*
225 * write key,read counter,write data,
226 * need this test_unit_ready operation.
227 */
228 ret = rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_TST_U_RDY, DMA_NONE, rpmb_lu_info.lu_index,
229 NULL, 0, 0);
230 }
231
232 return ret;
233 }
234
235 /* @retrun 0 rpmb key unwritten */
is_wr_ufs_rpmb_key(void)236 int is_wr_ufs_rpmb_key(void)
237 {
238 int ret = 0;
239 struct rpmb_data_frame *data_frame;
240 uint16_t msg_type;
241 uint16_t op_result;
242 uint8_t nonce[RPMB_NONCE_SIZE] = {
243 0xa5, 0x5a, 0xff, 0x00, 0xbe, 0xef, 0xbe, 0xef,
244 0xbe, 0xef, 0xbe, 0xef, 0x00, 0xff, 0x5a, 0xa5
245 };
246
247 ret = hba_test(rpmb_hba);
248 if (ret)
249 return ret;
250
251 if (rpmb_lu_info.log2blksz == 0) {
252 ret = prepare_rpmb_lu();
253 if(0 != ret)
254 return ret;
255 }
256
257 msg_type = RPMB_READ;
258 data_frame = memalign(ARCH_DMA_MINALIGN, RPMB_DATA_FRAME_SIZE);
259 if (!data_frame) {
260 printf("%s malloc error\n", __func__);
261 return -1;
262 }
263
264 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
265 u16_to_bytes(msg_type, data_frame->msg_type);
266 memcpy(data_frame->nonce, nonce, RPMB_NONCE_SIZE);
267 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
268 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
269
270
271 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
272 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_IN, DMA_FROM_DEVICE,
273 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
274
275 /* result check */
276 bytes_to_u16(data_frame->op_result, &op_result);
277 bytes_to_u16(data_frame->msg_type, &msg_type);
278 if (op_result == RPMB_RES_NO_AUTH_KEY) {
279 printf("%s rpmb key not write\n", __func__);
280 ret = 0;
281 } else {
282 printf("%s rpmb key has been written\n", __func__);
283 ret = -1;
284 }
285 free(data_frame);
286
287 return ret;
288 }
289
ufs_rpmb_read_writecount(void)290 uint32_t ufs_rpmb_read_writecount(void)
291 {
292 struct rpmb_data_frame *data_frame;
293 uint16_t msg_type;
294 uint16_t op_result;
295 uint32_t writecount;
296 uint8_t nonce[RPMB_NONCE_SIZE] = {
297 0xa5, 0x5a, 0xff, 0x00, 0xbe, 0xef, 0xbe, 0xef,
298 0xbe, 0xef, 0xbe, 0xef, 0x00, 0xff, 0x5a,0xa5
299 };
300 int ret = 0;
301
302 ret = hba_test(rpmb_hba);
303 if (ret)
304 return ret;
305
306 if (rpmb_lu_info.log2blksz == 0) {
307 ret = prepare_rpmb_lu();
308 if (ret != 0) {
309 printf("prepare rpmb unit failed!\n");
310 return ret;
311 }
312 }
313
314 msg_type = RPMB_READ_CNT;
315 data_frame = memalign(ARCH_DMA_MINALIGN, RPMB_DATA_FRAME_SIZE);
316 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
317 u16_to_bytes(msg_type, data_frame->msg_type);
318 memcpy(data_frame->nonce, nonce, RPMB_NONCE_SIZE);
319 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
320 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
321
322 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
323 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_IN, DMA_FROM_DEVICE,
324 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
325
326 /* result check */
327 bytes_to_u16(data_frame->op_result, &op_result);
328 bytes_to_u16(data_frame->msg_type, &msg_type);
329 if ((op_result == RPMB_RESULT_OK) &&
330 (msg_type == RPMB_RESP_WRITE_COUNTER_VAL_READ)) {
331 bytes_to_u32(data_frame->write_counter, &writecount);
332 printf("read write count successed\n");
333 free(data_frame);
334 return writecount;
335 }
336 else
337 printf(" read write count:0x%x ,msg_type:0x%x\n",
338 op_result,msg_type);
339 free(data_frame);
340
341 return 1;
342 }
343
344 /*
345 * blk_data: for save read data;
346 * blk_index: the block index for read;
347 * block_count: the read count;
348 * success return 0;
349 */
ufs_rpmb_blk_read(char * blk_data,uint8_t * key,uint16_t blk_index,uint16_t block_count)350 int ufs_rpmb_blk_read(char *blk_data, uint8_t *key, uint16_t blk_index, uint16_t block_count)
351 {
352 struct rpmb_data_frame *data_frame;
353 struct rpmb_data_frame *resp_buf;
354 uint16_t msg_type;
355 uint16_t op_result;
356 uint8_t nonce[RPMB_NONCE_SIZE] = {
357 0xa5, 0x5a, 0xff, 0x00, 0xbe, 0xef, 0xbe, 0xef,
358 0xbe, 0xef, 0xbe, 0xef, 0x00, 0xef, 0x5a,0xa5
359 };
360 int ret = 0;
361
362 ret = hba_test(rpmb_hba);
363 if (ret)
364 return ret;
365
366 if (rpmb_lu_info.log2blksz == 0) {
367 ret = prepare_rpmb_lu();
368 if (ret != 0)
369 return ret;
370 }
371
372 if (!blk_data) {
373 printf("rpmb_blk_read null \n");
374 return 0;
375 }
376
377 msg_type = RPMB_READ;
378 data_frame = memalign(ARCH_DMA_MINALIGN, RPMB_DATA_FRAME_SIZE);
379 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
380 u16_to_bytes(msg_type, data_frame->msg_type);
381 u16_to_bytes(blk_index, data_frame->address);
382 u16_to_bytes(block_count, data_frame->block_count);
383 memcpy(data_frame->nonce, nonce, RPMB_NONCE_SIZE);
384 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
385 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
386
387 resp_buf = memalign(ARCH_DMA_MINALIGN, RPMB_DATA_FRAME_SIZE * block_count);
388 memset(resp_buf, 0, RPMB_DATA_FRAME_SIZE * block_count);
389 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_IN, DMA_FROM_DEVICE,
390 rpmb_lu_info.lu_index, (void*)resp_buf, 0, block_count);
391
392 /* result check */
393 bytes_to_u16((resp_buf + block_count - 1)->op_result, &op_result);
394 bytes_to_u16((resp_buf + block_count - 1)->msg_type, &msg_type);
395 if ((op_result == RPMB_RESULT_OK) &&
396 (msg_type == RPMB_RESP_AUTH_DATA_READ)) {
397 uint8_t i = 0;
398 for (i = 0; i < block_count; i++)
399 memcpy((blk_data + i * RPMB_DATA_SIZE),
400 ((uint8_t *) (resp_buf + i) +
401 RPMB_STUFF_DATA_SIZE + RPMB_KEY_MAC_SIZE),
402 RPMB_DATA_SIZE);
403 printf("read successed\n");
404 free(resp_buf);
405 free(data_frame);
406 return block_count;
407 } else
408 printf("read write count:0x%x ,msg_type:0x%x\n", op_result, msg_type);
409
410 free(resp_buf);
411 free(data_frame);
412
413 return 0;
414 }
415
416 /*
417 * write_data: data for write
418 * blk_index: the block will be write to;
419 * success return 0
420 */
421
422 /* for single data */
ufs_rpmb_blk_write(char * write_data,uint8_t * key,uint16_t blk_index,uint16_t blk_count)423 int ufs_rpmb_blk_write(char *write_data, uint8_t *key, uint16_t blk_index, uint16_t blk_count)
424 {
425 struct rpmb_data_frame *data_frame;
426 uint16_t msg_type;
427 uint16_t op_result;
428 uint32_t writecount;
429 int ret = 0, i;
430
431
432 ret = hba_test(rpmb_hba);
433 if (ret)
434 return ret;
435
436 if(rpmb_lu_info.log2blksz == 0) {
437 ret = prepare_rpmb_lu();
438 if (ret != 0)
439 return ret;
440 }
441
442 if (!write_data)
443 return 1;
444
445 /* TODO: The following codes is multiple block write
446 * for(int i=0;i<(strlen(write_data)/RPMB_DATA_SIZE),i++){
447 */
448
449 msg_type = RPMB_WRITE;
450 data_frame = memalign(ARCH_DMA_MINALIGN, RPMB_DATA_FRAME_SIZE * blk_count);
451 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE * blk_count);
452 writecount = ufs_rpmb_read_writecount();
453
454 for (i = 0; i < blk_count; i++) {
455 u16_to_bytes(msg_type, data_frame[i].msg_type);
456 u16_to_bytes(blk_index, data_frame[i].address);
457 u16_to_bytes(blk_count, data_frame[i].block_count);
458 u32_to_bytes(writecount, data_frame[i].write_counter);
459 memcpy(data_frame[i].data, write_data, RPMB_DATA_SIZE);
460 write_data += RPMB_DATA_FRAME_SIZE;
461 }
462
463 ufs_rpmb_hmac(key, data_frame, blk_count, data_frame[blk_count - 1].key_mac);
464
465 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
466 rpmb_lu_info.lu_index, (void*)data_frame, 0, blk_count);
467
468 /* for read result req */
469 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
470 msg_type = RPMB_READ_RESP;
471 u16_to_bytes(msg_type, data_frame->msg_type);
472 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
473 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
474
475 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
476 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_IN, DMA_FROM_DEVICE,
477 rpmb_lu_info.lu_index, (void*)data_frame, 0, 1);
478
479 /* result check */
480 bytes_to_u16(data_frame->op_result, &op_result);
481 bytes_to_u16(data_frame->msg_type, &msg_type);
482 if ((op_result == RPMB_RESULT_OK) && (msg_type == RPMB_RESP_AUTH_DATA_WRITE)) {
483 printf(" data write successed\n");
484 free(data_frame);
485 return blk_count;
486 } else {
487 printf(" data write fail op_result:0x%x ,msg_type:0x%x\n", op_result, msg_type);
488 }
489
490 free(data_frame);
491
492 return 0;
493 }
494
495 /*
496 * key: the key will write must 32 len;
497 * len :must be 32;
498 * reutrn 0 success
499 */
ufs_rpmb_write_key(uint8_t * key,uint8_t len)500 int ufs_rpmb_write_key(uint8_t * key, uint8_t len)
501 {
502 struct rpmb_data_frame *data_frame = NULL;
503 uint16_t msg_type;
504 uint16_t op_result;
505 int ret = 0;
506 lbaint_t transfer_blkcnt = 0;
507
508 ret = hba_test(rpmb_hba);
509 if (ret)
510 return ret;
511
512 if (rpmb_lu_info.log2blksz == 0) {
513 ret = prepare_rpmb_lu();
514 if (ret != 0)
515 return ret;
516 }
517
518 /* rpmb_lu_info.log2blksz=0x08,256B */
519 transfer_blkcnt = RPMB_DATA_FRAME_SIZE >> (rpmb_lu_info.log2blksz);
520
521 if (!key || len != RPMB_KEY_MAC_SIZE)
522 return 1;
523
524 /* for write rpmb key req */
525 msg_type = RPMB_WRITE_KEY;
526 data_frame = memalign(ARCH_DMA_MINALIGN, RPMB_DATA_FRAME_SIZE);
527 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
528 u16_to_bytes(msg_type, data_frame->msg_type);
529 memcpy(data_frame->key_mac, key, RPMB_KEY_MAC_SIZE);
530
531 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
532 rpmb_lu_info.lu_index, (void*)data_frame, 0, transfer_blkcnt);
533
534 /* for read result req */
535 memset(data_frame, 0, RPMB_DATA_FRAME_SIZE);
536 msg_type = RPMB_READ_RESP;
537 u16_to_bytes(msg_type, data_frame->msg_type);
538
539 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
540 rpmb_lu_info.lu_index, (void*)data_frame, 0, transfer_blkcnt);
541
542 memset(data_frame, 0xcc, RPMB_DATA_FRAME_SIZE);
543 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_IN, DMA_FROM_DEVICE,
544 rpmb_lu_info.lu_index, (void*)data_frame, 0, transfer_blkcnt);
545
546 /* result check */
547 bytes_to_u16(data_frame->op_result, &op_result);
548 bytes_to_u16(data_frame->msg_type, &msg_type);
549 if ((op_result == RPMB_RESULT_OK) && (msg_type == RPMB_RESP_AUTH_KEY_PROGRAM)) {
550 printf(" key write successed\n");
551 free(data_frame);
552 return 0;
553 } else {
554 printf(" key write fail op_result:0x%x ,msg_type:0x%x\n", op_result, msg_type);
555 }
556
557 free(data_frame);
558
559 return 1;
560 }
561
ufs_read_desc(struct ufs_hba * hba,enum desc_idn desc_id,int desc_index,u8 * buf,u32 size)562 static int ufs_read_desc(struct ufs_hba *hba, enum desc_idn desc_id,
563 int desc_index, u8 *buf, u32 size)
564 {
565 return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size);
566 }
567
ufs_read_device_desc(u8 * buf,u32 size)568 int ufs_read_device_desc(u8 *buf, u32 size)
569 {
570 int ret = 0;
571
572 ret = hba_test(rpmb_hba);
573 if (ret)
574 return ret;
575
576 return ufs_read_desc(rpmb_hba, QUERY_DESC_IDN_DEVICE, 0, buf, size);
577 }
578
ufs_read_string_desc(int desc_index,u8 * buf,u32 size)579 int ufs_read_string_desc(int desc_index, u8 *buf, u32 size)
580 {
581 int ret = 0;
582
583 ret = hba_test(rpmb_hba);
584 if (ret)
585 return ret;
586
587 return ufs_read_desc(rpmb_hba, QUERY_DESC_IDN_STRING, desc_index, buf, size);
588 }
589
ufs_read_geo_desc(u8 * buf,u32 size)590 int ufs_read_geo_desc(u8 *buf, u32 size)
591 {
592 int ret = 0;
593
594 ret = hba_test(rpmb_hba);
595 if (ret)
596 return ret;
597
598 return ufs_read_desc(rpmb_hba, QUERY_DESC_IDN_GEOMETRY, 0, buf, size);
599 }
600
ufs_read_rpmb_unit_desc(u8 * buf,u32 size)601 int ufs_read_rpmb_unit_desc(u8 *buf, u32 size)
602 {
603 int ret = 0;
604
605 ret = hba_test(rpmb_hba);
606 if (ret)
607 return ret;
608
609 return ufs_read_desc(rpmb_hba, QUERY_DESC_IDN_UNIT, 0xc4, buf, size);
610 }
611
do_rpmb_op(struct rpmb_data_frame * frame_in,uint32_t in_cnt,struct rpmb_data_frame * frame_out,uint32_t out_cnt)612 int do_rpmb_op(struct rpmb_data_frame *frame_in, uint32_t in_cnt,
613 struct rpmb_data_frame *frame_out, uint32_t out_cnt)
614 {
615 uint16_t msg_type = 0;
616 int ret = 0;
617
618 ret = hba_test(rpmb_hba);
619 if (ret)
620 return ret;
621
622 if (rpmb_lu_info.log2blksz == 0) {
623 ret = prepare_rpmb_lu();
624 if (ret != 0) {
625 printf("prepare rpmb unit failed!\n");
626 return ret;
627 }
628 }
629
630 if (!frame_in || !frame_out || !in_cnt || !out_cnt) {
631 printf("Wrong rpmb parameters\n");
632 return -1;
633 }
634
635 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
636 rpmb_lu_info.lu_index, (void*)frame_in, 0, in_cnt);
637
638 bytes_to_u16(frame_in->msg_type, &msg_type);
639 if ((msg_type == RPMB_WRITE) || (msg_type == RPMB_WRITE_KEY) ||
640 (msg_type == RPMB_SEC_CONF_WRITE)) {
641 memset(&frame_in[0], 0, sizeof(frame_in[0]));
642 msg_type = RPMB_READ_RESP;
643 u16_to_bytes(msg_type, frame_in->msg_type);
644
645 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_OUT, DMA_TO_DEVICE,
646 rpmb_lu_info.lu_index, (void*)frame_in, 0, 1);
647 }
648
649 rpmb_send_scsi_cmd(rpmb_hba, UFS_OP_SECURITY_PROTOCOL_IN, DMA_FROM_DEVICE,
650 rpmb_lu_info.lu_index, (void*)frame_out, 0, out_cnt);
651 return 0;
652 }
653
ufs_rpmb_init(struct ufs_hba * hba)654 int ufs_rpmb_init(struct ufs_hba *hba)
655 {
656 rpmb_hba = hba;
657
658 return 0;
659 }
660