xref: /rk3399_rockchip-uboot/lib/optee_clientApi/tee_ufs_rpmb.c (revision 395c77b5f9b45eba4468a378527c654ac1160fc0)
1*395c77b5SHisping Lin /*
2*395c77b5SHisping Lin  * Copyright 2024, Rockchip Electronics Co., Ltd
3*395c77b5SHisping Lin  * hisping lin, <hisping.lin@rock-chips.com>
4*395c77b5SHisping Lin  *
5*395c77b5SHisping Lin  * SPDX-License-Identifier:	GPL-2.0+
6*395c77b5SHisping Lin  */
7*395c77b5SHisping Lin #include <common.h>
8*395c77b5SHisping Lin #include <stdlib.h>
9*395c77b5SHisping Lin #include <command.h>
10*395c77b5SHisping Lin #include <optee_include/OpteeClientRPC.h>
11*395c77b5SHisping Lin #include <optee_include/tee_rpc.h>
12*395c77b5SHisping Lin #include <optee_include/tee_rpc_types.h>
13*395c77b5SHisping Lin #include <optee_include/teesmc_v2.h>
14*395c77b5SHisping Lin #include <optee_include/tee_client_api.h>
15*395c77b5SHisping Lin #include "../../drivers/ufs/ufs.h"
16*395c77b5SHisping Lin #include "../../drivers/ufs/ufs-rockchip-rpmb.h"
17*395c77b5SHisping Lin 
18*395c77b5SHisping Lin /*
19*395c77b5SHisping Lin  * Execute an RPMB storage operation.
20*395c77b5SHisping Lin  */
21*395c77b5SHisping Lin #ifdef CONFIG_ROCKCHIP_UFS_RPMB
22*395c77b5SHisping Lin 
bedata_to_u16(uint8_t * d)23*395c77b5SHisping Lin static uint16_t bedata_to_u16(uint8_t *d)
24*395c77b5SHisping Lin {
25*395c77b5SHisping Lin 	return (d[0] << 8) + (d[1]);
26*395c77b5SHisping Lin }
27*395c77b5SHisping Lin 
bedata_to_u64(uint8_t * d)28*395c77b5SHisping Lin static uint64_t bedata_to_u64(uint8_t *d)
29*395c77b5SHisping Lin {
30*395c77b5SHisping Lin 	uint64_t data = 0;
31*395c77b5SHisping Lin 	uint64_t temp = 0;
32*395c77b5SHisping Lin 
33*395c77b5SHisping Lin 	for (int i = 0; i < 8; i++) {
34*395c77b5SHisping Lin 		temp = d[i];
35*395c77b5SHisping Lin 		data += (temp << ((7 - i) * 8));
36*395c77b5SHisping Lin 	}
37*395c77b5SHisping Lin 
38*395c77b5SHisping Lin 	return data;
39*395c77b5SHisping Lin }
40*395c77b5SHisping Lin 
u16_to_bedata(uint16_t src,uint8_t * d)41*395c77b5SHisping Lin static void u16_to_bedata(uint16_t src, uint8_t *d)
42*395c77b5SHisping Lin {
43*395c77b5SHisping Lin 	d[0] = (src >> 8) & 0xff;
44*395c77b5SHisping Lin 	d[1] = src & 0xff;
45*395c77b5SHisping Lin }
46*395c77b5SHisping Lin 
rpmb_data_req(struct rpmb_data_frame * req_frm,size_t req_nfrm,struct rpmb_data_frame * rsp_frm,size_t rsp_nfrm)47*395c77b5SHisping Lin static int rpmb_data_req(struct rpmb_data_frame *req_frm,
48*395c77b5SHisping Lin 			 size_t req_nfrm,
49*395c77b5SHisping Lin 			 struct rpmb_data_frame *rsp_frm,
50*395c77b5SHisping Lin 			 size_t rsp_nfrm)
51*395c77b5SHisping Lin {
52*395c77b5SHisping Lin 	struct rpmb_data_frame *req_packets = NULL;
53*395c77b5SHisping Lin 	struct rpmb_data_frame *rsp_packets = NULL;
54*395c77b5SHisping Lin 	uint16_t req_type;
55*395c77b5SHisping Lin 	int ret = -1;
56*395c77b5SHisping Lin 
57*395c77b5SHisping Lin 	req_packets = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(struct rpmb_data_frame) * req_nfrm);
58*395c77b5SHisping Lin 	if (!req_packets)
59*395c77b5SHisping Lin 		goto out;
60*395c77b5SHisping Lin 
61*395c77b5SHisping Lin 	rsp_packets = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(struct rpmb_data_frame) * rsp_nfrm);
62*395c77b5SHisping Lin 	if (!rsp_packets)
63*395c77b5SHisping Lin 		goto out;
64*395c77b5SHisping Lin 
65*395c77b5SHisping Lin 	memcpy(req_packets, req_frm, sizeof(struct rpmb_data_frame) * req_nfrm);
66*395c77b5SHisping Lin 
67*395c77b5SHisping Lin 	req_type = bedata_to_u16(req_packets->msg_type);
68*395c77b5SHisping Lin 
69*395c77b5SHisping Lin 	switch (req_type) {
70*395c77b5SHisping Lin 	case TEE_RPC_RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM:
71*395c77b5SHisping Lin 	case TEE_RPC_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: {
72*395c77b5SHisping Lin 		ret = do_rpmb_op(req_packets, req_nfrm, rsp_packets, rsp_nfrm);
73*395c77b5SHisping Lin 		break;
74*395c77b5SHisping Lin 	}
75*395c77b5SHisping Lin 	case TEE_RPC_RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: {
76*395c77b5SHisping Lin 		do_rpmb_op(req_packets, req_nfrm, rsp_packets, rsp_nfrm);
77*395c77b5SHisping Lin 		ret = TEEC_SUCCESS;
78*395c77b5SHisping Lin 		break;
79*395c77b5SHisping Lin 	}
80*395c77b5SHisping Lin 	case TEE_RPC_RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: {
81*395c77b5SHisping Lin 		uint16_t block_count;
82*395c77b5SHisping Lin 		block_count = bedata_to_u16(req_packets->block_count);
83*395c77b5SHisping Lin 		if (block_count == 0) {
84*395c77b5SHisping Lin 			u16_to_bedata(rsp_nfrm, req_packets->block_count);
85*395c77b5SHisping Lin 		}
86*395c77b5SHisping Lin 		ret = do_rpmb_op(req_packets, req_nfrm, rsp_packets, rsp_nfrm);
87*395c77b5SHisping Lin 		break;
88*395c77b5SHisping Lin 	}
89*395c77b5SHisping Lin 	default:
90*395c77b5SHisping Lin 		ret = TEEC_ERROR_BAD_PARAMETERS;
91*395c77b5SHisping Lin 		break;
92*395c77b5SHisping Lin 	}
93*395c77b5SHisping Lin 
94*395c77b5SHisping Lin 	for (int i = 0; i < rsp_nfrm; i++)
95*395c77b5SHisping Lin 		memcpy(rsp_frm + i, rsp_packets + i, sizeof(struct rpmb_data_frame));
96*395c77b5SHisping Lin 
97*395c77b5SHisping Lin out:
98*395c77b5SHisping Lin 	if (req_packets)
99*395c77b5SHisping Lin 		free(req_packets);
100*395c77b5SHisping Lin 
101*395c77b5SHisping Lin 	if (rsp_packets)
102*395c77b5SHisping Lin 		free(rsp_packets);
103*395c77b5SHisping Lin 
104*395c77b5SHisping Lin 	return ret;
105*395c77b5SHisping Lin }
106*395c77b5SHisping Lin 
rpmb_get_dev_info(struct tee_rpc_rpmb_dev_info * info)107*395c77b5SHisping Lin static int rpmb_get_dev_info(struct tee_rpc_rpmb_dev_info *info)
108*395c77b5SHisping Lin {
109*395c77b5SHisping Lin 	uint8_t manufacture_name_idx;
110*395c77b5SHisping Lin 	uint8_t rpmb_rw_blocks;
111*395c77b5SHisping Lin 	uint64_t rpmb_block_count;
112*395c77b5SHisping Lin 	uint8_t desc_buff[QUERY_DESC_MAX_SIZE] = { 0 };
113*395c77b5SHisping Lin 	uint8_t str_buff[QUERY_DESC_MAX_SIZE] = { 0 };
114*395c77b5SHisping Lin 	uint8_t geo_buff[QUERY_DESC_MAX_SIZE] = { 0 };
115*395c77b5SHisping Lin 	uint8_t unit_buf[QUERY_DESC_MAX_SIZE] = { 0 };
116*395c77b5SHisping Lin 
117*395c77b5SHisping Lin 	if (ufs_read_device_desc(desc_buff, sizeof(desc_buff))) {
118*395c77b5SHisping Lin 		printf("get device desc fail!\n");
119*395c77b5SHisping Lin 		return -1;
120*395c77b5SHisping Lin 	}
121*395c77b5SHisping Lin 	manufacture_name_idx = desc_buff[0x14];
122*395c77b5SHisping Lin 
123*395c77b5SHisping Lin 	if (ufs_read_string_desc(manufacture_name_idx, str_buff, sizeof(str_buff))) {
124*395c77b5SHisping Lin 		printf("get device desc fail!\n");
125*395c77b5SHisping Lin 		return -1;
126*395c77b5SHisping Lin 	}
127*395c77b5SHisping Lin 
128*395c77b5SHisping Lin 	if (str_buff[0] != 0x12) {
129*395c77b5SHisping Lin 		printf("manufacture name string length error!\n");
130*395c77b5SHisping Lin 		return -1;
131*395c77b5SHisping Lin 	}
132*395c77b5SHisping Lin 
133*395c77b5SHisping Lin 	if (sizeof(info->cid) != 0x10) {
134*395c77b5SHisping Lin 		printf("cid length error!\n");
135*395c77b5SHisping Lin 		return -1;
136*395c77b5SHisping Lin 	}
137*395c77b5SHisping Lin 
138*395c77b5SHisping Lin 	memcpy(info->cid, &str_buff[2], sizeof(info->cid));
139*395c77b5SHisping Lin 
140*395c77b5SHisping Lin 	if (ufs_read_geo_desc(geo_buff, sizeof(geo_buff))) {
141*395c77b5SHisping Lin 		printf("get geometry desc fail!\n");
142*395c77b5SHisping Lin 		return -1;
143*395c77b5SHisping Lin 	}
144*395c77b5SHisping Lin 	rpmb_rw_blocks = geo_buff[0x17];
145*395c77b5SHisping Lin 
146*395c77b5SHisping Lin 	if (ufs_read_rpmb_unit_desc(unit_buf, sizeof(unit_buf))) {
147*395c77b5SHisping Lin 		printf("get rpmb ubit desc fail!\n");
148*395c77b5SHisping Lin 		return -1;
149*395c77b5SHisping Lin 	}
150*395c77b5SHisping Lin 	rpmb_block_count = bedata_to_u64(&unit_buf[0x0B]);
151*395c77b5SHisping Lin 
152*395c77b5SHisping Lin 	info->rel_wr_sec_c = rpmb_rw_blocks;
153*395c77b5SHisping Lin 	info->rpmb_size_mult = rpmb_block_count / 512;
154*395c77b5SHisping Lin 	info->ret_code = 0;
155*395c77b5SHisping Lin 
156*395c77b5SHisping Lin 	return 0;
157*395c77b5SHisping Lin }
158*395c77b5SHisping Lin 
ufs_rpmb_process(t_teesmc32_arg * smc_arg)159*395c77b5SHisping Lin TEEC_Result ufs_rpmb_process(t_teesmc32_arg *smc_arg)
160*395c77b5SHisping Lin {
161*395c77b5SHisping Lin 	t_teesmc32_param *smc_param;
162*395c77b5SHisping Lin 	struct tee_rpc_rpmb_cmd *rpmb_req;
163*395c77b5SHisping Lin 	struct rpmb_data_frame *req_packets = NULL;
164*395c77b5SHisping Lin 	struct rpmb_data_frame *rsp_packets = NULL;
165*395c77b5SHisping Lin 	size_t req_num, rsp_num;
166*395c77b5SHisping Lin 	struct tee_rpc_rpmb_dev_info *dev_info;
167*395c77b5SHisping Lin 	TEEC_Result result = TEEC_SUCCESS;
168*395c77b5SHisping Lin 	TEEC_Result status;
169*395c77b5SHisping Lin 
170*395c77b5SHisping Lin 	if (smc_arg->num_params != 2) {
171*395c77b5SHisping Lin 		result = TEEC_ERROR_BAD_PARAMETERS;
172*395c77b5SHisping Lin 		goto exit;
173*395c77b5SHisping Lin 	}
174*395c77b5SHisping Lin 
175*395c77b5SHisping Lin 	smc_param = TEESMC32_GET_PARAMS(smc_arg);
176*395c77b5SHisping Lin 	rpmb_req = (struct tee_rpc_rpmb_cmd *)(size_t)
177*395c77b5SHisping Lin 		   smc_param[0].u.memref.buf_ptr;
178*395c77b5SHisping Lin 
179*395c77b5SHisping Lin 	switch (rpmb_req->cmd) {
180*395c77b5SHisping Lin 	case TEE_RPC_RPMB_CMD_DATA_REQ: {
181*395c77b5SHisping Lin 		req_packets = (struct rpmb_data_frame *)(rpmb_req + 1);
182*395c77b5SHisping Lin 		rsp_packets = (struct rpmb_data_frame *)(size_t)smc_param[1].u.memref.buf_ptr;
183*395c77b5SHisping Lin 		req_num = bedata_to_u16(req_packets->block_count);
184*395c77b5SHisping Lin 		req_num = (req_num == 0 ? 1 : req_num);
185*395c77b5SHisping Lin 		rsp_num = (rpmb_req->block_count == 0 ? 1 : rpmb_req->block_count);
186*395c77b5SHisping Lin 
187*395c77b5SHisping Lin 		status = rpmb_data_req(req_packets, req_num, rsp_packets, rsp_num);
188*395c77b5SHisping Lin 		if (status != 0)
189*395c77b5SHisping Lin 			result = TEEC_ERROR_GENERIC;
190*395c77b5SHisping Lin 		goto exit;
191*395c77b5SHisping Lin 	}
192*395c77b5SHisping Lin 	case TEE_RPC_RPMB_CMD_GET_DEV_INFO: {
193*395c77b5SHisping Lin 		dev_info = (struct tee_rpc_rpmb_dev_info *)
194*395c77b5SHisping Lin 			   (size_t)smc_param[1].u.memref.buf_ptr;
195*395c77b5SHisping Lin 
196*395c77b5SHisping Lin 		status = rpmb_get_dev_info(dev_info);
197*395c77b5SHisping Lin 		if (status != 0)
198*395c77b5SHisping Lin 			result = TEEC_ERROR_GENERIC;
199*395c77b5SHisping Lin 		goto exit;
200*395c77b5SHisping Lin 	}
201*395c77b5SHisping Lin 	default:
202*395c77b5SHisping Lin 		result = TEEC_ERROR_BAD_PARAMETERS;
203*395c77b5SHisping Lin 		goto exit;
204*395c77b5SHisping Lin 	}
205*395c77b5SHisping Lin 
206*395c77b5SHisping Lin exit:
207*395c77b5SHisping Lin 	smc_arg->ret = result;
208*395c77b5SHisping Lin 	smc_arg->ret_origin = TEEC_ORIGIN_API;
209*395c77b5SHisping Lin 
210*395c77b5SHisping Lin 	return result;
211*395c77b5SHisping Lin }
212*395c77b5SHisping Lin 
213*395c77b5SHisping Lin #else
214*395c77b5SHisping Lin 
ufs_rpmb_process(t_teesmc32_arg * smc_arg)215*395c77b5SHisping Lin TEEC_Result ufs_rpmb_process(t_teesmc32_arg *smc_arg)
216*395c77b5SHisping Lin {
217*395c77b5SHisping Lin 	smc_arg = smc_arg;
218*395c77b5SHisping Lin 	return TEEC_ERROR_NOT_IMPLEMENTED;
219*395c77b5SHisping Lin }
220*395c77b5SHisping Lin 
221*395c77b5SHisping Lin #endif
222