1 /*
2 * Copyright 2020, Rockchip Electronics Co., Ltd
3 * hisping lin, <hisping.lin@rock-chips.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8 #include <common.h>
9 #include <stdlib.h>
10 #include <command.h>
11 #include <boot_rkimg.h>
12 #include <part.h>
13 #include <optee_include/OpteeClientRkNewFs.h>
14 #include <optee_include/tee_client_api.h>
15
16 /*
17 *#define DEBUG_RKSS
18 *#define DEBUG_CLEAN_RKSS
19 */
20
21 /*
22 * RK Secure Storage Version 2
23 * Area0 Backup 0 Size : 256 kb <----> Area0 Backup 1 Size : 256 kb
24 * Area1 Backup 0 Size : 256 kb <----> Area1 Backup 1 Size : 256 kb
25 *
26 * ------ 1 section is 512 bytes -----
27 * ------ Area0 Backup0 section from 0 to 511 --------
28 * 1 section for file header [0]
29 * 1 section for used flags [1]
30 * - 1 byte = 2 flag
31 * 62 section for file tables [2-63]
32 * - size of table 128 bytes
33 * 447 section for data [64-510]
34 * 1 section for file footer [511]
35 *
36 * ------ Area0 Backup1 section from 512 to 1023 --------
37 * 1 section for file header [512]
38 * 1 section for used flags [513]
39 * - 1 byte = 2 flag
40 * 62 section for file tables [514-575]
41 * - size of table 128 bytes
42 * 447 section for data [576-1022]
43 * 1 section for file footer [1023]
44 *
45 * ------ Area1 Backup0 section from 1024 to 1535 --------
46 * 1 section for file header [1024]
47 * 1 section for used flags [1025]
48 * - 1 byte = 2 flag
49 * 62 section for file tables [1026-1087]
50 * - size of table 128 bytes
51 * 447 section for data [1088-1534]
52 * 1 section for file footer [1535]
53 *
54 * ------ Area1 Backup1 section from 1536 to 2047 --------
55 * 1 section for file header [1536]
56 * 1 section for used flags [1537]
57 * - 1 byte = 2 flag
58 * 62 section for file tables [1538-1599]
59 * - size of table 128 bytes
60 * 447 section for data [1600-2046]
61 * 1 section for file footer [2047]
62 */
63
64 /* define for backup */
65 #define RKSS_HEADER_INDEX 0
66 #define RKSS_HEADER_COUNT 1
67 #define RKSS_USEDFLAGS_INDEX 1
68 #define RKSS_USEDFLAGS_COUNT 1
69 #define RKSS_TABLE_INDEX 2
70 #define RKSS_TABLE_COUNT 62
71 #define RKSS_DATA_INDEX 64
72 #define RKSS_DATA_COUNT 447
73 #define RKSS_FOOTER_INDEX 511
74 #define RKSS_FOOTER_COUNT 1
75 #define RKSS_SECTION_COUNT 512
76
77 #define RKSS_MAX_AREA_NUM 8
78 #define RKSS_ACTIVE_AREA_NUM 2
79 #define RKSS_DATA_LEN 512
80 #define RKSS_EACH_FILEFOLDER_COUNT 4
81 #define RKSS_TABLE_SIZE 128
82 #define RKSS_NAME_MAX_LENGTH 112
83 #define RKSS_BACKUP_NUM 2
84 #define RKSS_TAG 0x524B5353
85
86 #define SYNC_NONE 0
87 #define SYNC_DOING 1
88 #define SYNC_DONE 2
89
90 struct rkss_file_header {
91 uint32_t tag;
92 uint32_t version;
93 uint32_t backup_count;
94 uint16_t backup_index;
95 uint16_t backup_dirty;
96 uint16_t sync_flag;
97 uint8_t reserve[494];
98 };
99 struct rkss_file_table {
100 uint32_t size;
101 uint16_t index;
102 uint8_t flags;
103 uint8_t used;
104 char name[RKSS_NAME_MAX_LENGTH];
105 uint8_t reserve[8];
106 };
107 struct rkss_file_footer {
108 uint8_t reserve[508];
109 uint32_t backup_count;
110 };
111 struct rkss_file {
112 struct rkss_file_header *header;
113 uint8_t *flags;
114 struct rkss_file_table *table;
115 uint8_t *data;
116 struct rkss_file_footer *footer;
117 };
118
119 /* RK Secure Storage Calls */
120 static char dir_cache[RKSS_NAME_MAX_LENGTH][12];
121 static int dir_num;
122 static int dir_seek;
123 static uint8_t *rkss_buffer[RKSS_MAX_AREA_NUM];
124 static struct rkss_file rkss_info[RKSS_MAX_AREA_NUM];
125
126 static struct blk_desc *dev_desc;
127 static disk_partition_t part_info;
128
check_security_exist(int print_flag)129 static int check_security_exist(int print_flag)
130 {
131 if (!dev_desc) {
132 dev_desc = rockchip_get_bootdev();
133 if (!dev_desc) {
134 printf("TEEC: %s: Could not find device\n", __func__);
135 return -1;
136 }
137
138 if (part_get_info_by_name(dev_desc,
139 "security", &part_info) < 0) {
140 dev_desc = NULL;
141 if (print_flag != 0)
142 printf("TEEC: Could not find security partition\n");
143 return -1;
144 }
145 }
146 return 0;
147 }
148
rkss_verify_usedflags(unsigned int area_index)149 static int rkss_verify_usedflags(unsigned int area_index)
150 {
151 uint8_t *flags;
152 int i, duel, flag, n, value;
153 uint8_t *flagw;
154 int used_count;
155
156 if (area_index >= RKSS_MAX_AREA_NUM) {
157 printf("TEEC: Not support area_index 0x%x\n", area_index);
158 return -1;
159 }
160
161 flags = rkss_info[area_index].flags;
162 if (flags == NULL) {
163 printf("TEEC: %s flags is null\n", __func__);
164 return -1;
165 }
166
167 used_count = RKSS_HEADER_COUNT +
168 RKSS_USEDFLAGS_COUNT +
169 RKSS_TABLE_COUNT;
170
171 for (i = 0; i < used_count; i++) {
172 duel = *(flags + (int)i/2);
173 flag = i & 0x1 ? duel & 0x0F : (duel & 0xF0) >> 4;
174 if (flag != 0x1)
175 goto init;
176 }
177
178 for (i = RKSS_FOOTER_INDEX; i < RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN * 2; i++) {
179 duel = *(flags + (int)i/2);
180 flag = i & 0x1 ? duel & 0x0F : (duel & 0xF0) >> 4;
181 if (flag != 0x1)
182 goto init;
183 }
184
185 debug("TEEC: %s: success.\n", __func__);
186 return 0;
187
188 init:
189 debug("TEEC: init usedflags section ...\n");
190 memset(flags, 0, RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN);
191 for (n = 0; n < used_count; n++) {
192 flagw = flags + (int)n/2;
193 value = 0x1;
194 *flagw = n & 0x1 ? (*flagw & 0xF0) | (value & 0x0F) :
195 (*flagw & 0x0F) | (value << 4);
196 }
197
198 for (n = RKSS_FOOTER_INDEX; n < RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN * 2; n++) {
199 flagw = flags + (int)n/2;
200 value = 0x1;
201 *flagw = n & 0x1 ? (*flagw & 0xF0) | (value & 0x0F) :
202 (*flagw & 0x0F) | (value << 4);
203 }
204 return 0;
205 }
206
207 #ifdef DEBUG_CLEAN_RKSS
rkss_storage_delete(uint32_t area_index)208 static int rkss_storage_delete(uint32_t area_index)
209 {
210 int ret;
211 uint32_t size;
212 uint8_t *delete_buff;
213
214 if (area_index >= RKSS_MAX_AREA_NUM) {
215 printf("TEEC: Not support area_index 0x%x\n", area_index);
216 return -1;
217 }
218
219 printf("TEEC: delete area index 0x%x!\n", area_index);
220 size = RKSS_SECTION_COUNT * RKSS_BACKUP_NUM * RKSS_DATA_LEN;
221 delete_buff = (uint8_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, size);
222 if (!delete_buff) {
223 printf("TEEC: Malloc failed!\n");
224 return -1;
225 }
226 memset(delete_buff, 0, size);
227 ret = blk_dwrite(dev_desc,
228 part_info.start + area_index * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM,
229 RKSS_SECTION_COUNT * RKSS_BACKUP_NUM, delete_buff);
230 if (ret != RKSS_SECTION_COUNT * RKSS_BACKUP_NUM) {
231 free(delete_buff);
232 printf("TEEC: blk_dwrite fail\n");
233 return -1;
234 }
235
236 if (delete_buff)
237 free(delete_buff);
238 printf("TEEC: delete area success!\n");
239 return 0;
240 }
241
rkss_storage_reset(void)242 static int rkss_storage_reset(void)
243 {
244 if (rkss_storage_delete(0) < 0)
245 return -1;
246 if (rkss_storage_delete(1) < 0)
247 return -1;
248 return 0;
249 }
250 #endif
251
252 #ifdef DEBUG_RKSS
rkss_dump(void * data,unsigned int len)253 static void rkss_dump(void *data, unsigned int len)
254 {
255 char *p = (char *)data;
256 unsigned int i = 0;
257
258 printf("-------------- DUMP %d --------------\n", len);
259 for (i = 0; i < len; i++) {
260 if (i % 32 == 0)
261 printf("\n");
262 printf("%02x ", *(p + i));
263 }
264 printf("\n");
265 printf("------------- DUMP END -------------\n");
266 }
267
rkss_dump_ptable(void)268 static void rkss_dump_ptable(void)
269 {
270 int i, j, n;
271 struct rkss_file_table *ptable;
272
273 printf("-------------- DUMP ptable --------------\n");
274
275 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
276 ptable = rkss_info[i].table;
277 if (rkss_info[i].table == NULL)
278 continue;
279 printf("--------------- area[%d] tables ------------\n", i);
280 for (j = 0; j < RKSS_TABLE_COUNT; j++) {
281 for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) {
282 printf("[%02d][%c] %s , inx:%d, size:%d\n",
283 j * RKSS_EACH_FILEFOLDER_COUNT + n,
284 ptable->used == 0 ? 'F':'T', ptable->name,
285 ptable->index, ptable->size);
286
287 ptable++;
288 }
289 }
290 }
291 printf("-------------- DUMP END --------------\n");
292 }
293
rkss_dump_usedflags(void)294 static void rkss_dump_usedflags(void)
295 {
296 int i;
297
298 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
299 if (rkss_info[i].flags == NULL)
300 continue;
301 printf("--------------- area[%d] flags ------------\n", i);
302 rkss_dump(rkss_info[i].flags, RKSS_USEDFLAGS_COUNT * RKSS_DATA_LEN);
303 }
304 }
305 #endif
306
rkss_read_multi_sections(unsigned int area_index,unsigned char * data,unsigned long index,unsigned int num)307 static int rkss_read_multi_sections(unsigned int area_index,
308 unsigned char *data, unsigned long index, unsigned int num)
309 {
310 if (area_index >= RKSS_MAX_AREA_NUM) {
311 printf("TEEC: %s area_index invalid\n", __func__);
312 return -1;
313 }
314 if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT ||
315 (index + num) > RKSS_SECTION_COUNT) {
316 printf("TEEC: %s index num invalid\n", __func__);
317 return -1;
318 }
319 if (rkss_buffer[area_index] == NULL) {
320 printf("TEEC: %s rkss_buffer is null\n", __func__);
321 return -1;
322 }
323 memcpy(data, rkss_buffer[area_index] + index * RKSS_DATA_LEN, num * RKSS_DATA_LEN);
324 return 0;
325 }
326
rkss_write_multi_sections(unsigned int area_index,unsigned char * data,unsigned long index,unsigned int num)327 static int rkss_write_multi_sections(unsigned int area_index,
328 unsigned char *data, unsigned long index, unsigned int num)
329 {
330 if (num == 0)
331 return 0;
332
333 if (area_index >= RKSS_MAX_AREA_NUM) {
334 printf("TEEC: %s area_index invalid\n", __func__);
335 return -1;
336 }
337
338 if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT ||
339 (index + num) > RKSS_SECTION_COUNT) {
340 printf("TEEC: %s index num invalid\n", __func__);
341 return -1;
342 }
343
344 if (rkss_buffer[area_index] == NULL) {
345 printf("TEEC: %s rkss_buffer is null\n", __func__);
346 return -1;
347 }
348
349 memcpy(rkss_buffer[area_index] + index * RKSS_DATA_LEN, data, num * RKSS_DATA_LEN);
350 rkss_info[area_index].header->backup_dirty = 1;
351 return 0;
352 }
353
rkss_get_fileinfo_by_index(int fd,struct rkss_file_table * ptable,unsigned int * out_area_index)354 static int rkss_get_fileinfo_by_index(int fd,
355 struct rkss_file_table *ptable, unsigned int *out_area_index)
356 {
357 struct rkss_file_table *p;
358 unsigned int area_index;
359
360 area_index = fd / (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT);
361 if (area_index >= RKSS_MAX_AREA_NUM) {
362 printf("TEEC: %s area_index invalid\n", __func__);
363 return -1;
364 }
365
366 p = rkss_info[area_index].table;
367 if (p == NULL) {
368 printf("TEEC: %s table is null\n", __func__);
369 return -1;
370 }
371
372 p += fd % (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT);
373 if (p->used != 1) {
374 debug("TEEC: %s unused table!\n", __func__);
375 return -1;
376 }
377 debug("TEEC: %s p->used = %d p->name=%s p->index=%d p->size=%d\n",
378 __func__, p->used, p->name, p->index, p->size);
379 memcpy(ptable, p, sizeof(struct rkss_file_table));
380 *out_area_index = area_index;
381 return 0;
382 }
383
rkss_get_fileinfo_by_name(char * filename,struct rkss_file_table * ptable,unsigned int * out_area_index)384 static int rkss_get_fileinfo_by_name(char *filename,
385 struct rkss_file_table *ptable, unsigned int *out_area_index)
386 {
387 int ret;
388 unsigned int i, j, n, len;
389 struct rkss_file_table *p;
390
391 len = strlen(filename);
392 if (len > RKSS_NAME_MAX_LENGTH - 1) {
393 printf("TEEC: filename is too long. length:%u\n", len);
394 return -1;
395 }
396
397 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
398 if (rkss_info[i].table == NULL)
399 continue;
400 for (j = 0; j < RKSS_TABLE_COUNT; j++) {
401 for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) {
402 p = rkss_info[i].table + j * RKSS_EACH_FILEFOLDER_COUNT + n;
403
404 if (p->used == 0)
405 continue;
406
407 if (!strcmp(p->name, filename)) {
408 debug("TEEC: %s: area%d hit table[%d/%d], index[%d/%d]\n",
409 __func__, i, j, RKSS_TABLE_COUNT, n, RKSS_EACH_FILEFOLDER_COUNT);
410 memcpy(ptable, p, sizeof(struct rkss_file_table));
411 *out_area_index = i;
412 ret = i * RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT +
413 j * RKSS_EACH_FILEFOLDER_COUNT + n;
414 return ret;
415 }
416
417 // Folder Matching
418 const char *split = "/";
419 char *last_inpos = filename;
420 char *last_svpos = p->name;
421 char *cur_inpos = NULL;
422 char *cur_svpos = NULL;
423
424 do {
425 cur_inpos = strstr(last_inpos, split);
426 cur_svpos = strstr(last_svpos, split);
427 int size_in = cur_inpos == NULL ?
428 (int)strlen(last_inpos) : cur_inpos - last_inpos;
429 int size_sv = cur_svpos == NULL ?
430 (int)strlen(last_svpos) : cur_svpos - last_svpos;
431
432 ret = memcmp(last_inpos, last_svpos, size_in);
433
434 last_inpos = cur_inpos + 1;
435 last_svpos = cur_svpos + 1;
436
437 if (size_in != size_sv || ret)
438 goto UNMATCHFOLDER;
439
440 } while (cur_inpos && cur_svpos);
441
442 debug("TEEC: Matched folder: %s\n", p->name);
443 return -100;
444 UNMATCHFOLDER:
445 debug("TEEC: Unmatched ...");
446 }
447 }
448 }
449 debug("TEEC: %s: file or dir no found!\n", __func__);
450 return -1;
451 }
452
rkss_get_dirs_by_name(char * filename)453 static int rkss_get_dirs_by_name(char *filename)
454 {
455 int ret;
456 unsigned int i, j, n, len;
457 struct rkss_file_table *p;
458
459 len = strlen(filename);
460 if (len > RKSS_NAME_MAX_LENGTH - 1) {
461 printf("TEEC: filename is too long. length:%u\n", len);
462 return -1;
463 }
464
465 dir_num = 0;
466 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
467 if (rkss_info[i].table == NULL)
468 continue;
469 for (j = 0; j < RKSS_TABLE_COUNT; j++) {
470 for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) {
471 p = rkss_info[i].table + j * RKSS_EACH_FILEFOLDER_COUNT + n;
472
473 if (p->used == 0)
474 continue;
475
476 // Full Matching
477 ret = memcmp(p->name, filename, strlen(filename));
478 debug("TEEC: comparing [fd:%d] : %s ?= %s, ret: %d\n",
479 (i * RKSS_TABLE_COUNT + j) * RKSS_EACH_FILEFOLDER_COUNT + n,
480 p->name, filename, ret);
481 if (!ret && strlen(p->name) > strlen(filename)) {
482 char *chk = p->name + strlen(filename);
483 if (*chk == '/') {
484 char *file = p->name + strlen(filename) + 1;
485 char *subdir = strtok(file, "/");
486 debug("TEEC: found: %s\n", subdir);
487 strcpy(dir_cache[dir_num], subdir);
488 ++dir_num;
489 }
490 }
491 }
492 }
493 }
494 return dir_num;
495 }
496
rkss_get_empty_section_from_usedflags(unsigned int area_index,int section_size)497 static int rkss_get_empty_section_from_usedflags(
498 unsigned int area_index, int section_size)
499 {
500 int i = 0;
501 int count0 = 0;
502
503 if (area_index >= RKSS_MAX_AREA_NUM) {
504 printf("TEEC: %s area_index invalid\n", __func__);
505 return -1;
506 }
507 if (rkss_info[area_index].flags == NULL) {
508 printf("TEEC: %s flags is null\n", __func__);
509 return -1;
510 }
511 for (i = 0; i < RKSS_SECTION_COUNT; i++) {
512 uint8_t *flag = rkss_info[area_index].flags + (int)i/2;
513 uint8_t value = i & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4;
514
515 if (value == 0x0) {
516 if (++count0 == section_size)
517 return (i + 1 - section_size);
518 } else {
519 count0 = 0;
520 }
521 }
522
523 printf("TEEC: Not enough space available in secure storage !\n");
524 return -10;
525 }
526
rkss_incref_multi_usedflags_sections(unsigned int area_index,unsigned int index,unsigned int num)527 static int rkss_incref_multi_usedflags_sections(
528 unsigned int area_index, unsigned int index, unsigned int num)
529 {
530 int value, i;
531 uint8_t *flag;
532
533 if (area_index >= RKSS_MAX_AREA_NUM) {
534 printf("TEEC: %s area_index invalid\n", __func__);
535 return -1;
536 }
537
538 if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT ||
539 (index + num) > RKSS_SECTION_COUNT) {
540 printf("TEEC: index[%d] out of range.\n", index);
541 return -1;
542 }
543 if (rkss_info[area_index].flags == NULL) {
544 printf("TEEC: %s flags is null\n", __func__);
545 return -1;
546 }
547
548 for (i = 0; i < num; i++, index++) {
549 flag = rkss_info[area_index].flags + (int)index / 2;
550 value = index & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4;
551 if (++value > 0xF) {
552 printf("TEEC: reference out of data: %d\n", value);
553 value = 0xF;
554 }
555 *flag = index & 0x1 ? (*flag & 0xF0) | (value & 0x0F) :
556 (*flag & 0x0F) | (value << 4);
557 }
558 rkss_info[area_index].header->backup_dirty = 1;
559 return 0;
560 }
561
rkss_decref_multi_usedflags_sections(unsigned int area_index,unsigned int index,unsigned int num)562 static int rkss_decref_multi_usedflags_sections(
563 unsigned int area_index, unsigned int index, unsigned int num)
564 {
565 int value, i;
566 uint8_t *flag;
567
568 if (area_index >= RKSS_MAX_AREA_NUM) {
569 printf("TEEC: %s area_index invalid\n", __func__);
570 return -1;
571 }
572
573 if (index >= RKSS_SECTION_COUNT || num > RKSS_SECTION_COUNT ||
574 (index + num) > RKSS_SECTION_COUNT) {
575 printf("TEEC: index[%d] out of range.\n", index);
576 return -1;
577 }
578 if (rkss_info[area_index].flags == NULL) {
579 printf("TEEC: %s flags is null\n", __func__);
580 return -1;
581 }
582
583 for (i = 0; i < num; i++, index++) {
584 flag = rkss_info[area_index].flags + (int)index / 2;
585 value = index & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4;
586 if (--value < 0) {
587 printf("TEEC: reference out of data: %d\n", value);
588 value = 0x0;
589 }
590 *flag = index & 0x1 ? (*flag & 0xF0) | (value & 0x0F) :
591 (*flag & 0x0F) | (value << 4);
592 }
593 rkss_info[area_index].header->backup_dirty = 1;
594 return 0;
595 }
596
rkss_get_remain_tables(struct rkss_file_table * p)597 static int rkss_get_remain_tables(struct rkss_file_table *p)
598 {
599 unsigned int i, n;
600 int count = 0;
601
602 if (p == NULL)
603 return -1;
604
605 for (i = 0; i < RKSS_TABLE_COUNT; i++) {
606 for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) {
607 if (p->used == 0)
608 count++;
609 p++;
610 }
611 }
612 return count;
613 }
614
rkss_get_remain_flags(uint8_t * flags)615 static int rkss_get_remain_flags(uint8_t *flags)
616 {
617 unsigned int i, value;
618 uint8_t *flag;
619 int count = 0;
620
621 if (flags == NULL)
622 return -1;
623
624 for (i = 0; i < RKSS_SECTION_COUNT; i++) {
625 flag = flags + (int)i / 2;
626 value = i & 0x1 ? *flag & 0x0F : (*flag & 0xF0) >> 4;
627 if (value == 0)
628 count++;
629 }
630 return count;
631 }
632
rkss_get_larger_area(void)633 static int rkss_get_larger_area(void)
634 {
635 int i, tables, flags, max_flags = 0;
636 int area_index = -1;
637
638 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
639 if (rkss_info[i].table == NULL ||
640 rkss_info[i].flags == NULL)
641 continue;
642 tables = rkss_get_remain_tables(rkss_info[i].table);
643 flags = rkss_get_remain_flags(rkss_info[i].flags);
644 if (tables > 0 && flags > 0 && flags > max_flags) {
645 max_flags = flags;
646 area_index = i;
647 }
648 }
649 return area_index;
650 }
651
rkss_write_area_empty_ptable(unsigned int area_index,struct rkss_file_table * pfile_table)652 static int rkss_write_area_empty_ptable(
653 unsigned int area_index, struct rkss_file_table *pfile_table)
654 {
655 int i, n, ret;
656 struct rkss_file_table *p;
657
658 if (rkss_info[area_index].table == NULL) {
659 printf("TEEC: %s table is null\n", __func__);
660 return -1;
661 }
662 for (i = 0; i < RKSS_TABLE_COUNT; i++) {
663 for (n = 0; n < RKSS_EACH_FILEFOLDER_COUNT; n++) {
664 p = rkss_info[area_index].table + i * RKSS_EACH_FILEFOLDER_COUNT + n;
665 if (p->used == 0) {
666 memcpy(p, pfile_table, sizeof(struct rkss_file_table));
667 p->used = 1;
668 debug("TEEC: write emt ptable : [%d,%d] name:%s, index:%d, size:%d, used:%d\n",
669 i, n, p->name, p->index, p->size, p->used);
670 rkss_info[area_index].header->backup_dirty = 1;
671 ret = area_index * RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT +
672 i * RKSS_EACH_FILEFOLDER_COUNT + n;
673 return ret;
674 }
675 }
676 }
677 printf("TEEC: No enough ptable space available in secure storage.\n");
678 return -1;
679 }
680
rkss_write_empty_ptable(struct rkss_file_table * pfile_table)681 static int rkss_write_empty_ptable(struct rkss_file_table *pfile_table)
682 {
683 int area_index;
684
685 area_index = rkss_get_larger_area();
686 if (area_index < 0) {
687 printf("TEEC: get area index fail\n");
688 return -1;
689 }
690
691 return rkss_write_area_empty_ptable(area_index, pfile_table);
692 }
693
rkss_write_back_ptable(int fd,struct rkss_file_table * pfile_table)694 static int rkss_write_back_ptable(
695 int fd, struct rkss_file_table *pfile_table)
696 {
697 struct rkss_file_table *p;
698 unsigned int area_index;
699
700 area_index = fd / (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT);
701 if (area_index >= RKSS_MAX_AREA_NUM) {
702 printf("TEEC: %s area_index invalid\n", __func__);
703 return -1;
704 }
705
706 p = rkss_info[area_index].table;
707 if (p == NULL) {
708 printf("TEEC: %s table is null\n", __func__);
709 return -1;
710 }
711
712 p += fd % (RKSS_TABLE_COUNT * RKSS_EACH_FILEFOLDER_COUNT);
713
714 memcpy(p, pfile_table, sizeof(struct rkss_file_table));
715 debug("TEEC: write ptable : name:%s, index:%d, size:%d, used:%d\n",
716 p->name, p->index, p->size, p->used);
717
718 rkss_info[area_index].header->backup_dirty = 1;
719 return 0;
720 }
721
rkss_storage_write(void)722 static int rkss_storage_write(void)
723 {
724 int ret, i;
725 int dirty_count = 0;
726 int dirty_num = 0;
727
728 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
729 if (rkss_info[i].header != NULL && rkss_info[i].header->backup_dirty == 1)
730 dirty_count++;
731 }
732
733 for (i = 0; i < RKSS_MAX_AREA_NUM; i++) {
734 if (rkss_info[i].header != NULL && rkss_info[i].header->backup_dirty == 1) {
735 rkss_info[i].header->backup_count++;
736 rkss_info[i].footer->backup_count = rkss_info[i].header->backup_count;
737 rkss_info[i].header->backup_index++;
738 if (rkss_info[i].header->backup_index >= RKSS_BACKUP_NUM)
739 rkss_info[i].header->backup_index = 0;
740 rkss_info[i].header->backup_dirty = 0;
741 dirty_num++;
742 rkss_info[i].header->sync_flag = SYNC_NONE;
743 if (dirty_count > 1) {
744 if (dirty_num == dirty_count)
745 rkss_info[i].header->sync_flag = SYNC_DONE;
746 else
747 rkss_info[i].header->sync_flag = SYNC_DOING;
748 }
749
750 if (rkss_info[i].header->backup_count == 0xffffffff) {
751 rkss_info[i].header->backup_count = 1;
752 rkss_info[i].footer->backup_count = 1;
753 ret = blk_dwrite(dev_desc,
754 part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
755 rkss_info[i].header->backup_index * RKSS_SECTION_COUNT,
756 RKSS_SECTION_COUNT, rkss_buffer[i]);
757 if (ret != RKSS_SECTION_COUNT) {
758 printf("TEEC: blk_dwrite fail\n");
759 return -1;
760 }
761
762 rkss_info[i].header->backup_count = 2;
763 rkss_info[i].footer->backup_count = 2;
764 rkss_info[i].header->backup_index++;
765 if (rkss_info[i].header->backup_index >= RKSS_BACKUP_NUM)
766 rkss_info[i].header->backup_index = 0;
767 ret = blk_dwrite(dev_desc,
768 part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
769 rkss_info[i].header->backup_index * RKSS_SECTION_COUNT,
770 RKSS_SECTION_COUNT, rkss_buffer[i]);
771 if (ret != RKSS_SECTION_COUNT) {
772 printf("TEEC: blk_dwrite fail\n");
773 return -1;
774 }
775 } else {
776 ret = blk_dwrite(dev_desc,
777 part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
778 rkss_info[i].header->backup_index * RKSS_SECTION_COUNT,
779 RKSS_SECTION_COUNT, rkss_buffer[i]);
780 if (ret != RKSS_SECTION_COUNT) {
781 printf("TEEC: blk_dwrite fail\n");
782 return -1;
783 }
784 }
785 }
786 }
787 return 0;
788 }
789
rkss_storage_clean_sync(void)790 static int rkss_storage_clean_sync(void)
791 {
792 for (int i = 0; i < RKSS_MAX_AREA_NUM; i++) {
793 if (rkss_info[i].header != NULL && rkss_info[i].header->sync_flag != SYNC_NONE) {
794 rkss_info[i].header->backup_count++;
795 rkss_info[i].footer->backup_count = rkss_info[i].header->backup_count;
796 rkss_info[i].header->backup_index++;
797 if (rkss_info[i].header->backup_index >= RKSS_BACKUP_NUM)
798 rkss_info[i].header->backup_index = 0;
799 rkss_info[i].header->backup_dirty = 0;
800 rkss_info[i].header->sync_flag = SYNC_NONE;
801
802 int ret = blk_dwrite(dev_desc,
803 part_info.start + i * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
804 rkss_info[i].header->backup_index * RKSS_SECTION_COUNT,
805 RKSS_SECTION_COUNT, rkss_buffer[i]);
806 if (ret != RKSS_SECTION_COUNT) {
807 printf("blk_dwrite fail \n");
808 return -1;
809 }
810 }
811 }
812 return 0;
813 }
814
rkss_storage_init(uint32_t area_index)815 static int rkss_storage_init(uint32_t area_index)
816 {
817 unsigned long ret = 0;
818 uint32_t size, i;
819 uint32_t max_ver = 0;
820 uint32_t max_index = 0;
821 uint32_t flags_offset, table_offset, data_offset, footer_offset;
822
823 if (area_index >= RKSS_MAX_AREA_NUM) {
824 printf("TEEC: Not support index=0x%x\n", area_index);
825 return -1;
826 }
827
828 size = RKSS_SECTION_COUNT * RKSS_DATA_LEN;
829 flags_offset = RKSS_USEDFLAGS_INDEX * RKSS_DATA_LEN;
830 table_offset = RKSS_TABLE_INDEX * RKSS_DATA_LEN;
831 data_offset = RKSS_DATA_INDEX * RKSS_DATA_LEN;
832 footer_offset = RKSS_FOOTER_INDEX * RKSS_DATA_LEN;
833
834 if (rkss_buffer[area_index] == NULL) {
835 /* Always use, no need to release */
836 rkss_buffer[area_index] = (uint8_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, size);
837 if (!(rkss_buffer[area_index])) {
838 printf("TEEC: Malloc failed!\n");
839 return -1;
840 }
841
842 /* Pointer initialization */
843 rkss_info[area_index].header = (struct rkss_file_header *)(rkss_buffer[area_index]);
844 rkss_info[area_index].flags = (uint8_t *)(rkss_buffer[area_index] + flags_offset);
845 rkss_info[area_index].table = (struct rkss_file_table *)(rkss_buffer[area_index] + table_offset);
846 rkss_info[area_index].data = (uint8_t *)(rkss_buffer[area_index] + data_offset);
847 rkss_info[area_index].footer = (struct rkss_file_footer *)(rkss_buffer[area_index] + footer_offset);
848
849 /* Find valid from (backup0 - backup1) */
850 for (i = 0; i < RKSS_BACKUP_NUM; i++) {
851 ret = blk_dread(dev_desc,
852 part_info.start +
853 area_index * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
854 i * RKSS_SECTION_COUNT,
855 RKSS_SECTION_COUNT, rkss_buffer[area_index]);
856 if (ret != RKSS_SECTION_COUNT) {
857 printf("TEEC: blk_dread fail\n");
858 return -1;
859 }
860
861 if ((rkss_info[area_index].header->tag == RKSS_TAG) &&
862 (rkss_info[area_index].footer->backup_count == rkss_info[area_index].header->backup_count)) {
863 if (max_ver < rkss_info[area_index].header->backup_count) {
864 max_index = i;
865 max_ver = rkss_info[area_index].header->backup_count;
866 }
867 }
868 }
869
870 if (max_ver) {
871 debug("TEEC: max_ver=%d, max_index=%d.\n",
872 max_ver, max_index);
873
874 if (max_index != (RKSS_BACKUP_NUM - 1)) {
875 ret = blk_dread(dev_desc,
876 part_info.start +
877 area_index * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
878 max_index * RKSS_SECTION_COUNT,
879 RKSS_SECTION_COUNT, rkss_buffer[area_index]);
880 if (ret != RKSS_SECTION_COUNT) {
881 printf("TEEC: blk_dread fail\n");
882 return -1;
883 }
884 }
885
886 if (rkss_info[area_index].header->version == RKSS_VERSION_V2) {
887 debug("TEEC: data version equal to image version, do nothing!\n");
888 } else if (rkss_info[area_index].header->version < RKSS_VERSION_V2) {
889 printf("TEEC: data version lower than image version!\n");
890 /* convert rkss version 2 to higher rkss version */
891 free(rkss_buffer[area_index]);
892 rkss_buffer[area_index] = NULL;
893 return -1;
894 } else {
895 printf("TEEC: data version higher than image version!\n");
896 printf("TEEC: please update image!\n");
897 free(rkss_buffer[area_index]);
898 rkss_buffer[area_index] = NULL;
899 return -1;
900 }
901 } else {
902 printf("TEEC: Reset area[%d] info...\n", area_index);
903 memset(rkss_buffer[area_index], 0, size);
904 rkss_info[area_index].header->tag = RKSS_TAG;
905 rkss_info[area_index].header->version = RKSS_VERSION_V2;
906 rkss_info[area_index].header->backup_count = 1;
907 rkss_info[area_index].footer->backup_count = 1;
908 /* Verify Usedflags Section */
909 if (rkss_verify_usedflags(area_index) < 0) {
910 printf("TEEC: rkss_verify_usedflags fail !\n");
911 return -1;
912 }
913 }
914 }
915 return 0;
916 }
917
rkss_check_sync_done(void)918 static int rkss_check_sync_done(void)
919 {
920 int ret;
921
922 if (rkss_info[0].header->sync_flag == SYNC_DOING &&
923 rkss_info[1].header->sync_flag != SYNC_DONE) {
924 //rkss_info[0] need rolled back
925 rkss_info[0].header->backup_index++;
926 if (rkss_info[0].header->backup_index >= RKSS_BACKUP_NUM)
927 rkss_info[0].header->backup_index = 0;
928 ret = blk_dread(dev_desc,
929 part_info.start + 0 * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
930 rkss_info[0].header->backup_index * RKSS_SECTION_COUNT,
931 RKSS_SECTION_COUNT, rkss_buffer[0]);
932 if (ret != RKSS_SECTION_COUNT) {
933 printf("blk_dread fail! \n");
934 return -1;
935 }
936 if ((rkss_info[0].header->tag != RKSS_TAG) ||
937 (rkss_info[0].footer->backup_count != rkss_info[0].header->backup_count)) {
938 printf("check header fail! \n");
939 return -1;
940 }
941
942 rkss_info[0].header->backup_index++;
943 if (rkss_info[0].header->backup_index >= RKSS_BACKUP_NUM)
944 rkss_info[0].header->backup_index = 0;
945 ret = blk_dwrite(dev_desc,
946 part_info.start + 0 * RKSS_SECTION_COUNT * RKSS_BACKUP_NUM +
947 rkss_info[0].header->backup_index * RKSS_SECTION_COUNT,
948 RKSS_SECTION_COUNT, rkss_buffer[0]);
949 if (ret != RKSS_SECTION_COUNT) {
950 printf("blk_dwrite fail! \n");
951 return -1;
952 }
953 }
954 ret = rkss_storage_clean_sync();
955 if (ret) {
956 printf("clean sync flag fail! \n");
957 return -1;
958 }
959 return 0;
960 }
961
ree_fs_new_open(size_t num_params,struct tee_ioctl_param * params)962 static uint32_t ree_fs_new_open(size_t num_params,
963 struct tee_ioctl_param *params)
964 {
965 char *filename;
966 int fd;
967 struct rkss_file_table p = {0};
968 unsigned int area_index;
969
970 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
971 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
972
973 filename = (char *)(size_t)params[1].u.memref.shm_id;
974 if (!filename)
975 return TEEC_ERROR_BAD_PARAMETERS;
976
977 if (strlen(filename) > RKSS_NAME_MAX_LENGTH) {
978 printf("TEEC: %s: file name too long. %s\n", __func__, filename);
979 return TEEC_ERROR_BAD_PARAMETERS;
980 }
981
982 debug("TEEC: %s open file: %s, len: %zu\n",
983 __func__, filename, strlen(filename));
984 fd = rkss_get_fileinfo_by_name(filename, &p, &area_index);
985 if (fd < 0) {
986 printf("TEEC: %s : no such file. %s\n", __func__, filename);
987 return TEEC_ERROR_ITEM_NOT_FOUND;
988 }
989
990 params[2].u.value.a = fd;
991 return TEEC_SUCCESS;
992 }
993
ree_fs_new_create(size_t num_params,struct tee_ioctl_param * params)994 static TEEC_Result ree_fs_new_create(size_t num_params,
995 struct tee_ioctl_param *params)
996 {
997 char *filename;
998 int fd;
999 int ret, num;
1000 struct rkss_file_table p = {0};
1001 unsigned int area_index;
1002 /* file open flags: O_RDWR | O_CREAT | O_TRUNC
1003 * if file exists, we must remove it first.
1004 */
1005 filename = (char *)(size_t)params[1].u.memref.shm_id;
1006 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1007 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1008 if (!filename)
1009 return TEEC_ERROR_BAD_PARAMETERS;
1010
1011 if (strlen(filename) > RKSS_NAME_MAX_LENGTH) {
1012 printf("TEEC: %s: file name too long. %s\n", __func__, filename);
1013 return TEEC_ERROR_BAD_PARAMETERS;
1014 }
1015
1016 debug("TEEC: %s create file: %s, len: %zu\n",
1017 __func__, filename, strlen(filename));
1018 fd = rkss_get_fileinfo_by_name(filename, &p, &area_index);
1019 if (fd >= 0) {
1020 printf("TEEC: %s : file exist, clear it. %s\n", __func__, filename);
1021 /* decrease ref from usedflags */
1022 num = p.size / RKSS_DATA_LEN + 1;
1023 ret = rkss_decref_multi_usedflags_sections(area_index, p.index, num);
1024 if (ret < 0) {
1025 printf("TEEC: rkss_decref_multi_usedflags_sections error !\n");
1026 return TEEC_ERROR_GENERIC;
1027 }
1028
1029 /* rm from ptable */
1030 memset(&p, 0, sizeof(struct rkss_file_table));
1031 ret = rkss_write_back_ptable(fd, &p);
1032 if (ret < 0) {
1033 printf("TEEC: %s : write back error %d\n", __func__, ret);
1034 return TEEC_ERROR_GENERIC;
1035 }
1036 }
1037
1038 strcpy(p.name, filename);
1039 p.index = 0;
1040 p.size = 0;
1041 p.used = 1;
1042 p.flags = RK_FS_R | RK_FS_W;
1043 fd = rkss_write_empty_ptable(&p);
1044 if (fd < 0) {
1045 printf("TEEC: %s : write empty ptable error. %s\n", __func__, filename);
1046 return TEEC_ERROR_GENERIC;
1047 }
1048
1049 params[2].u.value.a = fd;
1050
1051 return TEEC_SUCCESS;
1052 }
1053
ree_fs_new_close(size_t num_params,struct tee_ioctl_param * params)1054 static TEEC_Result ree_fs_new_close(size_t num_params,
1055 struct tee_ioctl_param *params)
1056 {
1057 debug("TEEC: %s !\n", __func__);
1058 UNREFERENCED_PARAMETER(params);
1059 UNREFERENCED_PARAMETER(num_params);
1060 return TEEC_SUCCESS;
1061 }
1062
ree_fs_new_read(size_t num_params,struct tee_ioctl_param * params)1063 static TEEC_Result ree_fs_new_read(size_t num_params,
1064 struct tee_ioctl_param *params)
1065 {
1066 uint8_t *data;
1067 size_t len;
1068 off_t offs;
1069 int fd;
1070 int ret;
1071 struct rkss_file_table p = {0};
1072 int di, section_num;
1073 uint8_t *temp_file_data;
1074 unsigned int area_index;
1075
1076 fd = params[0].u.value.b;
1077 offs = params[0].u.value.c;
1078
1079 data = (uint8_t *)(size_t)params[1].u.memref.shm_id;
1080 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1081 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1082
1083 if (!data)
1084 return TEEC_ERROR_BAD_PARAMETERS;
1085 len = params[1].u.memref.size;
1086
1087 debug("TEEC: %s! fd:%d, len:%zu, offs:%ld\n",
1088 __func__, fd, len, offs);
1089
1090 ret = rkss_get_fileinfo_by_index(fd, &p, &area_index);
1091 if (ret < 0) {
1092 printf("TEEC: unavailable fd: %d!\n", fd);
1093 return TEEC_ERROR_GENERIC;
1094 }
1095
1096 if (offs >= p.size)
1097 return TEEC_ERROR_BAD_PARAMETERS;
1098
1099 section_num = p.size / RKSS_DATA_LEN + 1;
1100 temp_file_data = malloc(section_num * RKSS_DATA_LEN);
1101 ret = rkss_read_multi_sections(area_index, temp_file_data, p.index, section_num);
1102 if (ret < 0) {
1103 printf("TEEC: unavailable file index!\n");
1104 free(temp_file_data);
1105 return TEEC_ERROR_GENERIC;
1106 }
1107 di = (offs + len) > p.size ? (p.size - offs) : len;
1108 memcpy(data, temp_file_data + offs, di);
1109 free(temp_file_data);
1110 temp_file_data = 0;
1111 params[1].u.memref.size = di;
1112
1113 return TEEC_SUCCESS;
1114 }
1115
ree_fs_new_write(size_t num_params,struct tee_ioctl_param * params)1116 static TEEC_Result ree_fs_new_write(size_t num_params,
1117 struct tee_ioctl_param *params)
1118 {
1119 uint8_t *data;
1120 size_t len;
1121 off_t offs;
1122 struct rkss_file_table p = {0};
1123 int ret, fd, new_size;
1124 int section_num;
1125 uint8_t *file_data = 0, *temp_file_data = 0;
1126 unsigned int area_index;
1127
1128 fd = params[0].u.value.b;
1129 offs = params[0].u.value.c;
1130
1131 data = (uint8_t *)(size_t)params[1].u.memref.shm_id;
1132 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1133 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1134 if (!data)
1135 return TEEC_ERROR_BAD_PARAMETERS;
1136 len = params[1].u.memref.size;
1137
1138 debug("TEEC: %s ! fd:%d, len:%zu, offs:%ld\n",
1139 __func__, fd, len, offs);
1140
1141 ret = rkss_get_fileinfo_by_index(fd, &p, &area_index);
1142 if (ret < 0) {
1143 printf("TEEC: %s: fd:%d unvailable!\n", __func__, fd);
1144 return TEEC_ERROR_BAD_PARAMETERS;
1145 }
1146
1147 new_size = offs + len > p.size ? offs + len : p.size;
1148 file_data = malloc(new_size);
1149 if (!file_data)
1150 return TEEC_ERROR_OUT_OF_MEMORY;
1151
1152 if (p.size != 0) {
1153 /* Read old file data out */
1154 section_num = p.size / RKSS_DATA_LEN + 1;
1155 temp_file_data = malloc(section_num * RKSS_DATA_LEN);
1156 ret = rkss_read_multi_sections(area_index, temp_file_data, p.index, section_num);
1157 if (ret < 0) {
1158 printf("TEEC: unavailable file index %d section_num %d\n", p.index, section_num);
1159 ret = TEEC_ERROR_GENERIC;
1160 goto out;
1161 }
1162 memcpy(file_data, temp_file_data, p.size);
1163 free(temp_file_data);
1164 temp_file_data = 0;
1165 ret = rkss_decref_multi_usedflags_sections(area_index, p.index, section_num);
1166 if (ret < 0) {
1167 printf("TEEC: rkss_decref_multi_usedflags_sections error !\n");
1168 ret = TEEC_ERROR_GENERIC;
1169 goto out;
1170 }
1171 }
1172
1173 /* update new file info */
1174 memcpy(file_data + offs, data, len);
1175 p.size = new_size;
1176 section_num = new_size / RKSS_DATA_LEN + 1;
1177 p.index = rkss_get_empty_section_from_usedflags(area_index, section_num);
1178 debug("TEEC: Get Empty section in %d\n", p.index);
1179 p.used = 1;
1180 ret = rkss_incref_multi_usedflags_sections(area_index, p.index, section_num);
1181 if (ret < 0) {
1182 printf("TEEC: rkss_incref_multi_usedflags_sections error !\n");
1183 ret = TEEC_ERROR_GENERIC;
1184 goto out;
1185 }
1186
1187 ret = rkss_write_back_ptable(fd, &p);
1188 if (ret < 0) {
1189 printf("TEEC: %s: write ptable error!\n", __func__);
1190 ret = TEEC_ERROR_GENERIC;
1191 goto out;
1192 }
1193
1194 /* write new file data */
1195 temp_file_data = malloc(section_num * RKSS_DATA_LEN);
1196 memset(temp_file_data, 0, section_num * RKSS_DATA_LEN);
1197 memcpy(temp_file_data, file_data, p.size);
1198 rkss_write_multi_sections(area_index, temp_file_data, p.index, section_num);
1199 free(temp_file_data);
1200 temp_file_data = 0;
1201
1202 out:
1203 if (file_data)
1204 free(file_data);
1205 if (temp_file_data) {
1206 free(temp_file_data);
1207 temp_file_data = 0;
1208 }
1209
1210 return TEEC_SUCCESS;
1211 }
1212
1213 /* TODO: update file data space */
ree_fs_new_truncate(size_t num_params,struct tee_ioctl_param * params)1214 static TEEC_Result ree_fs_new_truncate(size_t num_params,
1215 struct tee_ioctl_param *params)
1216 {
1217 size_t len;
1218 int fd, ret;
1219 struct rkss_file_table p = {0};
1220 unsigned int section_num_old, section_num_new;
1221 unsigned int area_index;
1222
1223 fd = params[0].u.value.b;
1224 len = params[0].u.value.c;
1225
1226 debug("TEEC: %s: fd:%d, lenth:%zu\n", __func__, fd, len);
1227
1228 ret = rkss_get_fileinfo_by_index(fd, &p, &area_index);
1229 if (ret < 0) {
1230 printf("TEEC: fd:%d unvailable!\n", fd);
1231 return TEEC_ERROR_GENERIC;
1232 }
1233 if (len > p.size) {
1234 printf("TEEC: truncate error!\n");
1235 return TEEC_ERROR_GENERIC;
1236 }
1237 section_num_old = p.size / RKSS_DATA_LEN + 1;
1238 section_num_new = len / RKSS_DATA_LEN + 1;
1239 ret = rkss_decref_multi_usedflags_sections(area_index, p.index + section_num_new, section_num_old - section_num_new);
1240 if (ret < 0) {
1241 printf("TEEC: rkss_decref_multi_usedflags_sections error !\n");
1242 ret = TEEC_ERROR_GENERIC;
1243 }
1244 p.size = len;
1245 ret = rkss_write_back_ptable(fd, &p);
1246 if (ret < 0) {
1247 printf("TEEC: %s: write ptable error!\n", __func__);
1248 return TEEC_ERROR_GENERIC;
1249 }
1250
1251 return TEEC_SUCCESS;
1252 }
1253
ree_fs_new_remove(size_t num_params,struct tee_ioctl_param * params)1254 static TEEC_Result ree_fs_new_remove(size_t num_params,
1255 struct tee_ioctl_param *params)
1256 {
1257 char *filename;
1258 struct rkss_file_table p = {0};
1259 int ret, fd, num;
1260 unsigned int area_index;
1261
1262 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1263 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1264
1265 filename = (char *)(size_t)params[1].u.memref.shm_id;
1266 if (!filename)
1267 return TEEC_ERROR_BAD_PARAMETERS;
1268
1269 ret = rkss_get_fileinfo_by_name(filename, &p, &area_index);
1270 if (ret < 0) {
1271 printf("TEEC: %s: no such file. %s\n", __func__, filename);
1272 return 0;
1273 }
1274 fd = ret;
1275
1276 debug("TEEC: %s! %s fd:%d index:%d size:%d\n",
1277 __func__, filename, fd, p.index, p.size);
1278
1279 /* decrease ref from usedflags */
1280 num = p.size / RKSS_DATA_LEN + 1;
1281 ret = rkss_decref_multi_usedflags_sections(area_index, p.index, num);
1282 if (ret < 0) {
1283 printf("TEEC: rkss_decref_multi_usedflags_sections error !\n");
1284 return TEEC_ERROR_GENERIC;
1285 }
1286
1287 /* rm from ptable */
1288 memset(&p, 0, sizeof(struct rkss_file_table));
1289 ret = rkss_write_back_ptable(fd, &p);
1290 if (ret < 0) {
1291 printf("TEEC: %s: write back error %d\n", __func__, ret);
1292 return TEEC_ERROR_GENERIC;
1293 }
1294
1295 return TEEC_SUCCESS;
1296 }
1297
ree_fs_new_rename(size_t num_params,struct tee_ioctl_param * params)1298 static TEEC_Result ree_fs_new_rename(size_t num_params,
1299 struct tee_ioctl_param *params)
1300 {
1301 char *old_fname;
1302 char *new_fname;
1303 struct rkss_file_table p = {0};
1304 int ret;
1305 unsigned int area_index;
1306
1307 old_fname = (char *)(size_t)params[1].u.memref.shm_id;
1308 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1309 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1310 if (!old_fname)
1311 return TEEC_ERROR_BAD_PARAMETERS;
1312
1313 new_fname = (char *)(size_t)params[2].u.memref.shm_id;
1314 debug("TEEC: params[2].u.memref.shm_id = 0x%llx params[2].u.memref.shm_offs = 0x%llx\n",
1315 params[2].u.memref.shm_id, params[2].u.memref.shm_offs);
1316 if (!new_fname)
1317 return TEEC_ERROR_BAD_PARAMETERS;
1318
1319 if (strlen(new_fname) > RKSS_NAME_MAX_LENGTH) {
1320 printf("TEEC: new file name too long. %s\n", new_fname);
1321 return TEEC_ERROR_BAD_PARAMETERS;
1322 }
1323
1324 debug("TEEC: rename: %s -> %s\n", old_fname, new_fname);
1325
1326 ret = rkss_get_fileinfo_by_name(old_fname, &p, &area_index);
1327 if (ret < 0) {
1328 printf("TEEC: filename: %s no found.\n", old_fname);
1329 return TEEC_ERROR_ITEM_NOT_FOUND;
1330 }
1331
1332 strcpy(p.name, new_fname);
1333
1334 ret = rkss_write_back_ptable(ret, &p);
1335 if (ret < 0) {
1336 printf("TEEC: write ptable error!\n");
1337 return TEEC_ERROR_GENERIC;
1338 }
1339
1340 return TEEC_SUCCESS;
1341 }
1342
ree_fs_new_opendir(size_t num_params,struct tee_ioctl_param * params)1343 static TEEC_Result ree_fs_new_opendir(size_t num_params,
1344 struct tee_ioctl_param *params)
1345 {
1346 char *dirname;
1347 int ret;
1348
1349 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1350 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1351
1352 dirname = (char *)(size_t)params[1].u.memref.shm_id;
1353 if (!dirname)
1354 return TEEC_ERROR_BAD_PARAMETERS;
1355
1356 dir_seek = 0;
1357 ret = rkss_get_dirs_by_name(dirname);
1358 if (ret < 0) {
1359 printf("TEEC: %s: error\n", __func__);
1360 return TEEC_ERROR_GENERIC;
1361 }
1362
1363 debug("TEEC: %s: %s, seek/num:%d/%d\n",
1364 __func__, dirname, dir_seek, dir_num);
1365 return TEEC_SUCCESS;
1366 }
1367
ree_fs_new_closedir(size_t num_params,struct tee_ioctl_param * params)1368 static TEEC_Result ree_fs_new_closedir(size_t num_params,
1369 struct tee_ioctl_param *params)
1370 {
1371 if (num_params != 1 ||
1372 (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) !=
1373 TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)
1374 return TEEC_ERROR_BAD_PARAMETERS;
1375
1376 dir_seek = 0;
1377 dir_num = 0;
1378
1379 return TEEC_SUCCESS;
1380 }
1381
ree_fs_new_readdir(size_t num_params,struct tee_ioctl_param * params)1382 static TEEC_Result ree_fs_new_readdir(size_t num_params,
1383 struct tee_ioctl_param *params)
1384 {
1385 char *dirname;
1386 size_t len;
1387 size_t dirname_len;
1388
1389 dirname = (char *)(size_t)params[1].u.memref.shm_id;
1390 debug("TEEC: params[1].u.memref.shm_id = 0x%llx params[1].u.memref.shm_offs = 0x%llx\n",
1391 params[1].u.memref.shm_id, params[1].u.memref.shm_offs);
1392 if (!dirname)
1393 return TEEC_ERROR_BAD_PARAMETERS;
1394 len = params[1].u.memref.size;
1395
1396 debug("TEEC: seek/num:%d/%d\n", dir_seek, dir_num);
1397 if (dir_seek == dir_num) {
1398 params[1].u.memref.size = 0;
1399 debug("TEEC: %s: END\n", __func__);
1400 return TEEC_ERROR_BAD_STATE;
1401 }
1402
1403 dirname_len = strlen(dir_cache[dir_seek]) + 1;
1404 params[1].u.memref.size = dirname_len;
1405 if (dirname_len > len)
1406 return TEEC_ERROR_SHORT_BUFFER;
1407
1408 strcpy(dirname, dir_cache[dir_seek]);
1409 ++dir_seek;
1410
1411 debug("TEEC: %s: %s\n", __func__, dirname);
1412
1413 return TEEC_SUCCESS;
1414 }
1415
tee_supp_rk_fs_init_v2(void)1416 int tee_supp_rk_fs_init_v2(void)
1417 {
1418 assert(sizeof(struct rkss_file_table) == RKSS_TABLE_SIZE);
1419 assert(RKSS_DATA_LEN / sizeof(struct rkss_file_table) == RKSS_EACH_FILEFOLDER_COUNT);
1420
1421 if (check_security_exist(0) < 0)
1422 return 0;
1423
1424 /* clean secure storage */
1425 #ifdef DEBUG_CLEAN_RKSS
1426 if (rkss_storage_reset() < 0)
1427 return -1;
1428 #endif
1429
1430 for (uint32_t i = 0; i < RKSS_ACTIVE_AREA_NUM; i++) {
1431 if (rkss_storage_init(i) < 0)
1432 return -1;
1433 }
1434
1435 if (rkss_check_sync_done() < 0)
1436 return -1;
1437
1438 #ifdef DEBUG_RKSS
1439 rkss_dump_ptable();
1440 rkss_dump_usedflags();
1441 #endif
1442
1443 return 0;
1444 }
1445
tee_supp_param_is_value(struct tee_ioctl_param * param)1446 static bool tee_supp_param_is_value(struct tee_ioctl_param *param)
1447 {
1448 switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
1449 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
1450 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
1451 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
1452 return true;
1453 default:
1454 return false;
1455 }
1456 }
1457
1458 static int rkss_step;
tee_supp_rk_fs_process_v2(size_t num_params,struct tee_ioctl_param * params)1459 int tee_supp_rk_fs_process_v2(size_t num_params,
1460 struct tee_ioctl_param *params)
1461 {
1462 uint32_t ret;
1463
1464 if (!num_params || !tee_supp_param_is_value(params))
1465 return TEEC_ERROR_BAD_PARAMETERS;
1466
1467 switch (params->u.value.a) {
1468 case OPTEE_MRF_OPEN:
1469 debug(">>>>>>> [%d] OPTEE_MRF_OPEN!\n", rkss_step++);
1470 ret = ree_fs_new_open(num_params, params);
1471 break;
1472 case OPTEE_MRF_CREATE:
1473 debug(">>>>>>> [%d] OPTEE_MRF_CREATE!\n", rkss_step++);
1474 ret = ree_fs_new_create(num_params, params);
1475 break;
1476 case OPTEE_MRF_CLOSE:
1477 debug(">>>>>>> [%d] OPTEE_MRF_CLOSE!\n", rkss_step++);
1478 ret = ree_fs_new_close(num_params, params);
1479 rkss_storage_write();
1480 rkss_storage_clean_sync();
1481 break;
1482 case OPTEE_MRF_READ:
1483 debug(">>>>>>> [%d] OPTEE_MRF_READ!\n", rkss_step++);
1484 ret = ree_fs_new_read(num_params, params);
1485 break;
1486 case OPTEE_MRF_WRITE:
1487 debug(">>>>>>> [%d] OPTEE_MRF_WRITE!\n", rkss_step++);
1488 ret = ree_fs_new_write(num_params, params);
1489 break;
1490 case OPTEE_MRF_TRUNCATE:
1491 debug(">>>>>>> [%d] OPTEE_MRF_TRUNCATE!\n", rkss_step++);
1492 ret = ree_fs_new_truncate(num_params, params);
1493 break;
1494 case OPTEE_MRF_REMOVE:
1495 debug(">>>>>>> [%d] OPTEE_MRF_REMOVE!\n", rkss_step++);
1496 ret = ree_fs_new_remove(num_params, params);
1497 rkss_storage_write();
1498 rkss_storage_clean_sync();
1499 break;
1500 case OPTEE_MRF_RENAME:
1501 debug(">>>>>>> [%d] OPTEE_MRF_RENAME!\n", rkss_step++);
1502 ret = ree_fs_new_rename(num_params, params);
1503 rkss_storage_write();
1504 rkss_storage_clean_sync();
1505 break;
1506 case OPTEE_MRF_OPENDIR:
1507 debug(">>>>>>> [%d] OPTEE_MRF_OPENDIR!\n", rkss_step++);
1508 ret = ree_fs_new_opendir(num_params, params);
1509 break;
1510 case OPTEE_MRF_CLOSEDIR:
1511 debug(">>>>>>> [%d] OPTEE_MRF_CLOSEDIR!\n", rkss_step++);
1512 ret = ree_fs_new_closedir(num_params, params);
1513 break;
1514 case OPTEE_MRF_READDIR:
1515 debug(">>>>>>> [%d] OPTEE_MRF_READDIR!\n", rkss_step++);
1516 ret = ree_fs_new_readdir(num_params, params);
1517 break;
1518 default:
1519 ret = TEEC_ERROR_BAD_PARAMETERS;
1520 break;
1521 }
1522 return ret;
1523 }
1524