xref: /OK3568_Linux_fs/external/rktoolkit/vendor_storage.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* V2.1:
2  *	1. remove VENDOR_SN_ID len limit
3  *	2. add custom id
4  *	3. exten max vendor string len to 1024
5  *	4. support file read/write
6  *	5. support build a library
7  */
8 
9 #include <fcntl.h>
10 #include <sys/ioctl.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <stdbool.h>
16 #include "vendor_storage.h"
17 
18 #define VENDOR_STORAGE_DEBUG
19 #ifdef VENDOR_STORAGE_DEBUG
20 #define DEBUG(fmt, args...)	fprintf(stdout, "[Debug] "fmt, ##args)
21 #else
22 #define DEBUG(fmt, args...)
23 #endif
24 #define INFO(fmt, args...)	fprintf(stdout, "[INFO] "fmt, ##args)
25 #define ERROR(fmt, args...)	fprintf(stderr, "[ERROR] "fmt, ##args)
26 
27 typedef		unsigned short	    uint16;
28 typedef		unsigned int	    uint32;
29 typedef		unsigned char	    uint8;
30 
31 #define VENDOR_MAX_SIZE		1024
32 #define VENDOR_REQ_TAG		0x56524551
33 #define VENDOR_READ_IO		_IOW('v', 0x01, unsigned int)
34 #define VENDOR_WRITE_IO		_IOW('v', 0x02, unsigned int)
35 
36 #define VENDOR_ID_MAX	16
37 #define VENDOR_CMD_CUSTOM_LEN	sizeof("VENDOR_CUSTOM_ID")
38 static char *vendor_id_table[] = {
39 	"VENDOR_SN_ID",
40 	"VENDOR_WIFI_MAC_ID",
41 	"VENDOR_LAN_MAC_ID",
42 	"VENDOR_BT_MAC_ID",
43 	"VENDOR_HDCP_14_HDMI_ID",
44 	"VENDOR_HDCP_14_DP_ID",
45 	"VENDOR_HDCP_2x_ID",
46 	"VENDOR_DRM_KEY_ID",
47 	"VENDOR_PLAYREADY_Cert_ID",
48 	"VENDOR_ATTENTION_KEY_ID",
49 	"VENDOR_PLAYREADY_ROOT_KEY_0_ID",
50 	"VENDOR_PLAYREADY_ROOT_KEY_1_ID",
51 	"VENDOR_SENSOR_CALIBRATION_ID",
52 	"VENODR_RESERVE_ID_14",
53 	"VENDOR_IMEI_ID",
54 	"VENDOR_CUSTOM_ID" /* CUSTOM_ID must be last one */
55 };
56 
57 #define VENDOR_PR_HEX		0
58 #define VENDOR_PR_STRING	1
59 
60 /* Set custom_id to hex print default */
61 #define GET_PR_FORMAT(ID, FORMAT) \
62 	if ((ID) == VENDOR_IMEI_ID || (ID) == VENDOR_SN_ID) \
63 		FORMAT = VENDOR_PR_STRING; \
64 	else \
65 		FORMAT = VENDOR_PR_HEX;
66 
67 struct rk_vendor_req {
68 	uint32 tag;
69 	uint16 id;
70 	uint16 len;
71 	uint8 data[1024];
72 };
73 
74 #ifndef BUILD_LIB_VENDOR_STORAGE
75 static char *argv0;
76 
rknand_print_string_data(uint8 * s,struct rk_vendor_req * buf,uint32 len)77 static void rknand_print_string_data(uint8 *s, struct rk_vendor_req *buf, uint32 len)
78 {
79 	unsigned int i;
80 
81 	for (i = 0; i < len; i++)
82 		printf("%c", buf->data[i]);
83 	fprintf(stdout, "\n");
84 }
85 
rknand_print_hex_data(uint8 * s,struct rk_vendor_req * buf,uint32 len)86 static void rknand_print_hex_data(uint8 *s, struct rk_vendor_req *buf, uint32 len)
87 {
88 	unsigned int i, line;
89 
90 	line = 0;
91 	for (i = 0; i < len; i++) {
92 		if (i & 0x000f) {
93 			printf(" %02x", buf->data[i]);
94 		} else {
95 			printf("\n %04x-%04x: %02x",
96 			       line << 4,
97 			       (line << 4) | 0xf,
98 			       buf->data[i]);
99 			line++;
100 		}
101 	}
102 
103 	fprintf(stdout, "\n");
104 }
105 
rknand_print_data(uint8 * s,struct rk_vendor_req * buf,uint32 len,int pr_type)106 static void rknand_print_data(uint8 *s, struct rk_vendor_req *buf,
107 				  uint32 len, int pr_type)
108 {
109 	DEBUG("%s\n",s);
110 	DEBUG("tag = %d // id = %d // len = %d // data = %p\n", buf->tag, buf->id, buf->len, buf->data);
111 
112 	INFO("%s:", (buf->id > VENDOR_ID_MAX) ?
113 		       "VENDOR_CUSTOM_ID" : vendor_id_table[buf->id - 1]);
114 
115 	if (pr_type)
116 		rknand_print_string_data(s, buf, len);
117 	else
118 		rknand_print_hex_data(s, buf, len);
119 }
120 
vendor_storage_read(int cmd,int pr_type,char * output)121 static int vendor_storage_read(int cmd, int pr_type, char *output)
122 {
123 	uint32 i;
124 	int ret ;
125 	uint8 p_buf[sizeof(struct rk_vendor_req)]; /* malloc req buffer or used extern buffer */
126 	struct rk_vendor_req *req;
127 	FILE *foutput = NULL;
128 
129 	DEBUG("%s id = %d\n", __func__, cmd);
130 
131 	req = (struct rk_vendor_req *)p_buf;
132 	memset(p_buf, 0, 100);
133 	int sys_fd = open("/dev/vendor_storage", O_RDWR, 0);
134 	if(sys_fd < 0){
135 		ERROR("vendor_storage open fail\n");
136 		return -1;
137 	}
138 
139 	req->tag = VENDOR_REQ_TAG;
140 	req->id = cmd;
141 	req->len = VENDOR_MAX_SIZE;
142 
143 	ret = ioctl(sys_fd, VENDOR_READ_IO, req);
144 
145 	if(ret){
146 		ERROR("vendor read error %d\n", ret);
147 		return -1;
148 	}
149 	close(sys_fd);
150 
151 	rknand_print_data("vendor read:", req, req->len, pr_type);
152 	if (output) {
153 		foutput=fopen(output,"wb");
154 		if (!foutput) {
155 			ERROR("failed to save %s\n", output);
156 			return 0;
157 		}
158 		fwrite(req->data, req->len, 1, foutput);
159 		fclose(foutput);
160 		INFO("save output to %s\n", output);
161 	}
162 
163 	return 0;
164 }
165 
vendor_storage_write(int cmd,char * num,int pr_type,int len)166 static int vendor_storage_write(int cmd, char *num, int pr_type, int len)
167 {
168 	uint32 i;
169 	int ret ;
170 	uint8 p_buf[sizeof(struct rk_vendor_req)]; /* malloc req buffer or used extern buffer */
171 	struct rk_vendor_req *req;
172 
173 	DEBUG("%s id = %d\n", __func__, cmd);
174 	req = (struct rk_vendor_req *)p_buf;
175 	int sys_fd = open("/dev/vendor_storage",O_RDWR,0);
176 	if(sys_fd < 0){
177 		ERROR("vendor_storage open fail\n");
178 		return -1;
179 	}
180 
181 	req->tag = VENDOR_REQ_TAG;
182 	req->id = cmd;
183 
184 	req->len = len;
185 	DEBUG("%s: strlen = %d\n", __func__, req->len);
186 	memcpy(req->data, num, req->len);
187 
188 	ret = ioctl(sys_fd, VENDOR_WRITE_IO, req);
189 	if(ret){
190 		ERROR("vendor write error\n");
191 		return -1;
192 	}
193 
194 	rknand_print_data("vendor write:", req, req->len, pr_type);
195 	return 0;
196 }
197 
usage(void)198 static void usage(void)
199 {
200 	int i;
201 
202 	fprintf(stderr,
203 		"vendor storage tool - Revision: 2.0 \n\n"
204 		"%s [-r/w <vendor_id> -t <pr_type> -i <input>] [-R]\n"
205 		"  -r           Read specify vendor_id\n"
206 		"  -R           Read common vendor_id\n"
207 		"  -w           Write specify vendor_id\n"
208 		"  -t           print type\n"
209 		"  -i           input string\n"
210 		"  <vendor_id>  There are %d types\n",
211 		argv0, VENDOR_ID_MAX);
212 	for (i = 0; i < VENDOR_ID_MAX; i++)
213 		fprintf(stderr,
214 		"               \"%s\"\n",
215 		vendor_id_table[i]);
216 	fprintf(stderr,
217 		"               And custom can define other id like\n"
218 		"               VENDOR_CUSTOM_ID_1A (define ID = 26)\n");
219 	fprintf(stderr,
220 		"  <pr_type>    In write case, used with -i <input>\n"
221 		"               There are 3 types\n"
222 		"               \"hex\": <input> must be hex form like 0123\n"
223 		"               \"string\": <input> must be ASCII string\n"
224 		"               \"file\": <input> must be path to file\n"
225 		"               Note: If use \"file\" and -i with read, it means save storage to file\n"
226 		"Examples:\n"
227 		"  %s -w VENDOR_CUSTOM_ID_1A -t file -i /userdata/test.bin\n"
228 		"                       write userdata/test.bin to storage\n"
229 		"                       Or -t string -i test_storage\n"
230 		"                       write string \"test_storage\" to storage\n"
231 		"                       ID = 26\n"
232 		"  %s -r VENDOR_CUSTOM_ID_1A -t file -i /userdata/read.bin\n"
233 		"                       read storage(ID=26) to userdata/read.bin\n"
234 		"                       Or -t string\n"
235 		"                       print storage(ID=26) with ASCII string\n",
236 		argv0, argv0);
237 	exit(1);
238 }
239 
vendor_len_mask(int cmd,int len,int cnt)240 static int vendor_len_mask(int cmd, int len, int cnt)
241 {
242 	if (cnt != len) {
243 		ERROR("%s must be %d bytes!!!\n",
244 		       vendor_id_table[cmd - 1], len);
245 		return -1;
246 	}
247 	return 0;
248 }
249 
is_hex(char c)250 static bool is_hex(char c)
251 {
252 	if (c < '0' || (c > '9' && c < 'A') ||
253 	    (c > 'F' && c < 'a') || c > 'f')
254 		return false;
255 	return true;
256 }
257 
char_to_hex(char c)258 static char char_to_hex(char c)
259 {
260 	if (c >= '0' && c <= '9')
261 		return c - '0';
262 	else if (c >= 'a' && c <= 'f')
263 		return c - ('a' - 10);
264 	else
265 		return c - ('A' - 10);
266 }
267 
hex_string_format(char * str,char * hex_str)268 static int hex_string_format(char *str, char *hex_str)
269 {
270 	int i, tmp;
271 
272 	tmp = strlen(str);
273 	if (tmp & 1)
274 		return 0;
275 
276 	for (i = 0; i < tmp; i++) {
277 		if (!is_hex(str[i])) {
278 			ERROR("[%s] must be HEX input\n", __func__);
279 			return 0;
280 		}
281 
282 		/* string to hex */
283 		str[i] = char_to_hex(str[i]);
284 		if (i & 1)
285 			hex_str[(i - 1) >> 1] = (str[i - 1] << 4) | str[i];
286 	}
287 	hex_str[i >> 1] = 0;
288 
289 	return i >> 1;
290 }
291 
vendor_get_custom_id(char * cmd)292 static int vendor_get_custom_id(char *cmd)
293 {
294 	int id;
295 
296 	/* Check vendor_custom_id */
297 	if (cmd[VENDOR_CMD_CUSTOM_LEN - 1] != '_' ||
298 	    !is_hex(cmd[VENDOR_CMD_CUSTOM_LEN]) ||
299 	    !is_hex(cmd[VENDOR_CMD_CUSTOM_LEN + 1])) {
300 		goto head_error;
301 	}
302 
303 	id = (char_to_hex(cmd[VENDOR_CMD_CUSTOM_LEN]) << 4) |
304 	     char_to_hex(cmd[VENDOR_CMD_CUSTOM_LEN + 1]);
305 
306 	return id;
307 head_error:
308 	return -1;
309 }
310 
vendor_storage_get_id(char * cmd)311 static int vendor_storage_get_id(char *cmd)
312 {
313 	int i, id;
314 
315 	for (i = 0; i < VENDOR_ID_MAX; i++) {
316 		if (!memcmp(optarg, vendor_id_table[i], strlen(vendor_id_table[i]))) {
317 			if (i == (VENDOR_CUSTOM_ID - 1)) {
318 				id = vendor_get_custom_id(optarg);
319 				if (id < 0) {
320 					usage();
321 					return -1;
322 				}
323 			} else {
324 				id = i + 1;
325 			}
326 			break;
327 		}
328 	}
329 
330 	if (i == VENDOR_ID_MAX)
331 		return -1;
332 
333 	return id;
334 }
335 
336 #define OPTION_FLAG_R		(0)
337 #define OPTION_FLAG_W		(!0)
main(int argc,char ** argv)338 int main(int argc, char **argv)
339 {
340 	int opt, i;
341 	int id = -1;
342 	int pr_type = -1;
343 	int flag_rw, flag_file = 0;
344 	unsigned char *vendor_hex = NULL;
345 	FILE *finput = NULL;
346 	long int size;
347 
348 	argv0 = argv[0];
349 	while ((opt = getopt(argc, argv, "hRr:w:t:i:")) > 0) {
350 		switch (opt) {
351 		case 'r':
352 			id = vendor_storage_get_id(optarg);
353 			if (id < 0) {
354 				ERROR("form_error, check cmd with -h\n");
355 				return -1;
356 			}
357 			flag_rw = OPTION_FLAG_R;
358 			break;
359 		case 'R':
360 			/* Read Common Vendor ID */
361 			for (i = 0; i < VENDOR_HDCP_2x_ID; i++) {
362 				GET_PR_FORMAT(i + 1, pr_type);
363 				vendor_storage_read(i + 1, pr_type, NULL);
364 			}
365 			return 0;
366 			break;
367 		case 'w':
368 			id = vendor_storage_get_id(optarg);
369 			if (id < 0) {
370 				ERROR("form_error, check cmd with -h\n");
371 				return -1;
372 			}
373 			flag_rw = OPTION_FLAG_W;
374 			break;
375 
376 		case 't':
377 			if (!memcmp(optarg, "string", strlen("string"))) {
378 				pr_type = VENDOR_PR_STRING;
379 			} else if (!memcmp(optarg, "hex", strlen("hex"))) {
380 				pr_type = VENDOR_PR_HEX;
381 			} else {
382 				pr_type = VENDOR_PR_HEX;
383 				flag_file = 1;
384 			}
385 			break;
386 		case 'i':
387 			vendor_hex = strdup(optarg);
388 			DEBUG("intput = %s\n", vendor_hex);
389 			break;
390 		case 'h':
391 			usage();
392 			break;
393 		default:
394 			ERROR("Unknown option: %c\n", opt);
395 			usage();
396 			break;
397 		}
398 	}
399 
400 	if (id < 0) {
401 		ERROR("Set id first\n");
402 		goto error;
403 	}
404 
405 	if (id <= VENDOR_HDCP_2x_ID) {
406 		GET_PR_FORMAT(id, pr_type);
407 	}
408 
409 	if (pr_type < 0) {
410 		INFO("Set hex output default\n");
411 		pr_type = VENDOR_PR_HEX;
412 	}
413 
414 	if (!vendor_hex && (flag_rw & OPTION_FLAG_W)) {
415 		ERROR("No input\n");
416 		goto error;
417 	}
418 
419 	if (flag_rw == OPTION_FLAG_R) {
420 		vendor_storage_read(id, pr_type,
421 				    flag_file ? vendor_hex: NULL);
422 	} else {
423 		if (flag_file) {
424 			finput = fopen(vendor_hex, "rb");
425 			if (!finput) {
426 				ERROR("Can't open %s\n", vendor_hex);
427 				goto error;
428 			}
429 			free(vendor_hex);
430 
431 			fseek(finput, 0, SEEK_END);
432 			size = ftell(finput);
433 			DEBUG("size = %d\n", size);
434 			fseek(finput, 0, SEEK_SET);
435 			vendor_hex = malloc(size + 1);
436 			fread(vendor_hex, 1, size, finput);
437 		} else if (pr_type == VENDOR_PR_HEX) {
438 			size = hex_string_format(vendor_hex, vendor_hex);
439 			if (!size) {
440 				ERROR("input is not hex form\n");
441 				goto error;
442 			}
443 		} else if (pr_type == VENDOR_PR_STRING) {
444 			size = strlen(vendor_hex);
445 		}
446 
447 		vendor_storage_write(id, vendor_hex, pr_type, size);
448 	}
449 
450 	if (finput)
451 		fclose(finput);
452 	if (vendor_hex)
453 		free(vendor_hex);
454 
455 	return 0;
456 
457 error_file:
458 	if (finput)
459 		fclose(finput);
460 error:
461 	if (vendor_hex)
462 		free(vendor_hex);
463 	return -1;
464 }
465 #endif
466 
467 #ifdef BUILD_LIB_VENDOR_STORAGE
rkvendor_read(int vendor_id,char * data,int size)468 int rkvendor_read(int vendor_id, char *data, int size)
469 {
470 	int ret ;
471 	uint8 p_buf[sizeof(struct rk_vendor_req)]; /* malloc req buffer or used extern buffer */
472 	struct rk_vendor_req *req;
473 
474 	req = (struct rk_vendor_req *)p_buf;
475 	memset(p_buf, 0, sizeof(struct rk_vendor_req));
476 	int sys_fd = open("/dev/vendor_storage", O_RDONLY);
477 	if(sys_fd < 0){
478 		fprintf(stderr, "vendor_storage open fail\n");
479 		return -1;
480 	}
481 
482 	req->tag = VENDOR_REQ_TAG;
483 	req->id = vendor_id;
484 	req->len = VENDOR_MAX_SIZE;
485 
486 	ret = ioctl(sys_fd, VENDOR_READ_IO, req);
487 	close(sys_fd);
488 	if (ret) {
489 		fprintf(stderr, "vendor read error %d\n", ret);
490 		return -1;
491 	}
492 
493 	if ( size < req->len ) {
494 		fprintf(stderr, "vendor storage: param size is lower then read size %d\n", strlen(req->data) );
495 		return -1;
496 	}
497 
498 	memcpy(data, req->data, req->len);
499 	return 0;
500 }
501 
rkvendor_write(int vendor_id,const char * data,int size)502 int rkvendor_write(int vendor_id, const char *data, int size)
503 {
504 	int ret ;
505 	uint8 p_buf[sizeof(struct rk_vendor_req)]; /* malloc req buffer or used extern buffer */
506 	struct rk_vendor_req *req;
507 
508 	if (size > VENDOR_MAX_SIZE) {
509 		fprintf(stderr, "vendor storage input data overflow\n");
510 		return -1;
511 	}
512 
513 	req = (struct rk_vendor_req *)p_buf;
514 	int sys_fd = open("/dev/vendor_storage",O_RDWR,0);
515 	if (sys_fd < 0) {
516 		fprintf(stderr, "vendor storage open fail\n");
517 		return -1;
518 	}
519 
520 	req->tag = VENDOR_REQ_TAG;
521 	req->id = vendor_id;
522 
523 	req->len = size;
524 	memcpy(req->data, data, req->len);
525 
526 	ret = ioctl(sys_fd, VENDOR_WRITE_IO, req);
527 	close(sys_fd);
528 	if (ret) {
529 		fprintf(stderr, "vendor write error\n");
530 		return -1;
531 	}
532 
533 	return 0;
534 }
535 #endif
536