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