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