xref: /rk3399_rockchip-uboot/drivers/ufs/ufs-rockchip-rpmb.c (revision 395c77b5f9b45eba4468a378527c654ac1160fc0)
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