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