xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/utils/mkuffs.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2   This file is part of UFFS, the Ultra-low-cost Flash File System.
3 
4   Copyright (C) 2005-2009 Ricky Zheng <[email protected]>
5 
6   UFFS is free software; you can redistribute it and/or modify it under
7   the GNU Library General Public License as published by the Free Software
8   Foundation; either version 2 of the License, or (at your option) any
9   later version.
10 
11   UFFS is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   or GNU Library General Public License, as applicable, for more details.
15 
16   You should have received a copy of the GNU General Public License
17   and GNU Library General Public License along with UFFS; if not, write
18   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19   Boston, MA  02110-1301, USA.
20 
21   As a special exception, if other files instantiate templates or use
22   macros or inline functions from this file, or you compile this file
23   and link it with other works to produce a work based on this file,
24   this file does not by itself cause the resulting work to be covered
25   by the GNU General Public License. However the source code for this
26   file must still be made available in accordance with section (3) of
27   the GNU General Public License v2.
28 
29   This exception does not invalidate any other reasons why a work based
30   on this file might be covered by the GNU General Public License.
31 */
32 
33 /**
34  * \file uffs_test.c
35  * \brief uffs test main entry
36  * \author Ricky Zheng
37  */
38 
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include "uffs_config.h"
43 #include "uffs/uffs_os.h"
44 #include "uffs/uffs_public.h"
45 #include "uffs/uffs_fs.h"
46 #include "uffs/uffs_utils.h"
47 #include "uffs/uffs_core.h"
48 #include "uffs/uffs_mtb.h"
49 
50 #include "cmdline.h"
51 #include "uffs_fileem.h"
52 
53 #define PFX NULL
54 #define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
55 #define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
56 
57 #if CONFIG_USE_STATIC_MEMORY_ALLOCATOR > 0
main()58 int main()
59 {
60 	MSGLN("Static memory allocator is not supported.");
61 	return 0;
62 }
63 #else
64 
65 extern struct cli_commandset * get_helper_cmds(void);
66 extern struct cli_commandset * get_test_cmds(void);
67 extern void femu_init_uffs_device(uffs_Device *dev);
68 
69 static int conf_command_line_mode = 0;
70 static int conf_verbose_mode = 0;
71 
72 static int conf_exec_script = 0;
73 static char script_command[256];
74 
75 #define DEFAULT_EMU_FILENAME "uffsemfile.bin"
76 const char * conf_emu_filename = DEFAULT_EMU_FILENAME;
77 
78 
79 /* default basic parameters of the NAND device */
80 #define PAGES_PER_BLOCK_DEFAULT			32
81 #define PAGE_DATA_SIZE_DEFAULT			512
82 #define PAGE_SPARE_SIZE_DEFAULT			16
83 #define STATUS_BYTE_OFFSET_DEFAULT		5
84 #define TOTAL_BLOCKS_DEFAULT			128
85 #define ECC_OPTION_DEFAULT				UFFS_ECC_SOFT
86 //#define ECC_OPTION_DEFAULT			UFFS_ECC_HW
87 //#define ECC_OPTION_DEFAULT			UFFS_ECC_HW_AUTO
88 
89 #define MAX_MOUNT_TABLES		10
90 #define MAX_MOUNT_POINT_NAME	32
91 
92 static int conf_pages_per_block = PAGES_PER_BLOCK_DEFAULT;
93 static int conf_page_data_size = PAGE_DATA_SIZE_DEFAULT;
94 static int conf_page_spare_size = PAGE_SPARE_SIZE_DEFAULT;
95 static int conf_status_byte_offset = STATUS_BYTE_OFFSET_DEFAULT;
96 static int conf_total_blocks = TOTAL_BLOCKS_DEFAULT;
97 static int conf_ecc_option = ECC_OPTION_DEFAULT;
98 static int conf_ecc_size = 0; // 0 - Let UFFS choose the size
99 
100 static const char *g_ecc_option_strings[] = UFFS_ECC_OPTION_STRING;
101 
102 static struct uffs_MountTableEntrySt conf_mounts[MAX_MOUNT_TABLES] = {{0}};
103 static uffs_Device conf_devices[MAX_MOUNT_TABLES] = {{0}};
104 static char mount_point_name[MAX_MOUNT_TABLES][MAX_MOUNT_POINT_NAME] = {{0}};
105 
setup_storage(struct uffs_StorageAttrSt * attr)106 static void setup_storage(struct uffs_StorageAttrSt *attr)
107 {
108 	attr->total_blocks = conf_total_blocks;				/* total blocks */
109 	attr->page_data_size = conf_page_data_size;			/* page data size */
110 	attr->spare_size = conf_page_spare_size;			/* page spare size */
111 	attr->pages_per_block = conf_pages_per_block;		/* pages per block */
112 
113 	attr->block_status_offs = conf_status_byte_offset;	/* block status offset is 5th byte in spare */
114 	attr->ecc_opt = conf_ecc_option;					/* ECC option */
115 	attr->ecc_size = conf_ecc_size;						/* ECC size */
116 	attr->layout_opt = UFFS_LAYOUT_UFFS;				/* let UFFS handle layout */
117 }
118 
119 
setup_device(uffs_Device * dev)120 static void setup_device(uffs_Device *dev)
121 {
122 	dev->Init = femu_InitDevice;
123 	dev->Release = femu_ReleaseDevice;
124 	dev->attr = femu_GetStorage();
125 }
126 
setup_emu_private(uffs_FileEmu * emu)127 static void setup_emu_private(uffs_FileEmu *emu)
128 {
129 	memset(emu, 0, sizeof(uffs_FileEmu));
130 	emu->emu_filename = conf_emu_filename;
131 }
132 
init_uffs_fs(void)133 static int init_uffs_fs(void)
134 {
135 	static int bIsFileSystemInited = 0;
136 	struct uffs_MountTableEntrySt *mtbl = &(conf_mounts[0]);
137 	struct uffs_ConfigSt cfg = {
138 		0,			// bc_caches - default
139 		0,			// page_buffers - default
140 		0,			// dirty_pages - default
141 		0,			// dirty_groups - default
142 		0,			// reserved_free_blocks - default
143 	};
144 
145 	if (bIsFileSystemInited)
146 		return -4;
147 
148 	bIsFileSystemInited = 1;
149 
150 	while (mtbl->dev) {
151 
152 		memcpy(&mtbl->dev->cfg, &cfg, sizeof(struct uffs_ConfigSt));
153 
154 #if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0
155 		uffs_MemSetupSystemAllocator(&mtbl->dev->mem);
156 #endif
157 		setup_device(mtbl->dev);
158 		uffs_RegisterMountTable(mtbl);
159 		mtbl++;
160 	}
161 
162 	// mount partitions
163 	for (mtbl = &(conf_mounts[0]); mtbl->mount != NULL; mtbl++) {
164 		uffs_Mount(mtbl->mount);
165 	}
166 
167 	return uffs_InitFileSystemObjects() == U_SUCC ? 0 : -1;
168 }
169 
release_uffs_fs(void)170 static int release_uffs_fs(void)
171 {
172 	int ret = 0;
173 	uffs_MountTable *mtb;
174 
175 	for (mtb = &(conf_mounts[0]); ret == 0 && mtb->mount != NULL; mtb++) {
176 		uffs_UnMount(mtb->mount);
177 	}
178 
179 	if (ret == 0)
180 		ret = (uffs_ReleaseFileSystemObjects() == U_SUCC ? 0 : -1);
181 
182 	return ret;
183 }
184 
185 /* mount point arg: /sys/,100,-1 */
parse_mount_point(char * arg,int m_idx)186 static int parse_mount_point(char *arg, int m_idx)
187 {
188 	int start = 0, end = -1;
189 	char *p = arg;
190 	struct uffs_MountTableEntrySt *mtbl = &(conf_mounts[m_idx]);
191 
192 	while(*p && *p != ',' && *p != ' ' && *p != '\t')
193 		p++;
194 
195 	if (*p == 0 || p == arg)
196 		return -1;
197 
198 	mtbl->mount = &(mount_point_name[m_idx][0]);
199 	memcpy((char *)mtbl->mount, arg, p - arg);
200 	((char *)(mtbl->mount))[p - arg] = 0;
201 
202 	p++;
203 	arg = p;
204 	while(*p && *p != ',' && *p != ' ' && *p != '\t')
205 		p++;
206 
207 	if (p != arg) {
208 		if (sscanf(arg, "%i", &start) < 1)
209 			return -1;
210 		p++;
211 		arg = p;
212 
213 		while(*p && *p != ',' && *p != ' ' && *p != '\t')
214 			p++;
215 
216 		if (p != arg) {
217 			if (sscanf(arg, "%i", &end) < 1)
218 				return -1;
219 		}
220 	}
221 	mtbl->start_block = start;
222 	mtbl->end_block = end;
223 	mtbl->dev = &(conf_devices[m_idx]);
224 
225 	return 0;
226 }
227 
parse_options(int argc,char * argv[])228 static int parse_options(int argc, char *argv[])
229 {
230     int iarg;
231     int usage = 0;
232 	int m_idx = 0;
233     static char em_file[128];
234 	int i;
235 
236     for (iarg = 1; iarg < argc && !usage; iarg++) {
237         const char *arg = argv[iarg];
238 
239         if (arg[0] == '-') {
240             if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) {
241                 usage++;
242             }
243             else if (!strcmp(arg, "-f") || !strcmp(arg, "--file")) {
244                 if (++iarg >= argc)
245 					usage++;
246 				else {
247 					strcpy(em_file, argv[iarg]);
248 					conf_emu_filename = (const char *)em_file;
249 				}
250             }
251             else if (!strcmp(arg, "-c") || !strcmp(arg, "--command-line")) {
252 				conf_command_line_mode = 1;
253             }
254             else if (!strcmp(arg, "-p") || !strcmp(arg, "--page-size")) {
255                 if (++iarg >= argc)
256 					usage++;
257                 else if (sscanf(argv[iarg], "%i", &conf_page_data_size) < 1)
258 					usage++;
259 				if (conf_page_data_size <= 0 || conf_page_data_size > UFFS_MAX_PAGE_SIZE) {
260 					MSGLN("ERROR: Invalid page data size");
261 					usage++;
262 				}
263             }
264             else if (!strcmp(arg, "-s") || !strcmp(arg, "--spare-size")) {
265                 if (++iarg >= argc)
266 					usage++;
267                 else if (sscanf(argv[iarg], "%i", &conf_page_spare_size) < 1)
268 					usage++;
269 				if (conf_page_spare_size < sizeof(struct uffs_TagStoreSt) + 1 ||
270 					(conf_page_spare_size % 4) != 0 || conf_page_spare_size > UFFS_MAX_SPARE_SIZE) {
271 					MSGLN("ERROR: Invalid spare size");
272 					usage++;
273 				}
274             }
275             else if (!strcmp(arg, "-o") || !strcmp(arg, "--status-offset")) {
276                 if (++iarg >= argc)
277 					usage++;
278                 else if (sscanf(argv[iarg], "%i", &conf_status_byte_offset) < 1)
279 					usage++;
280 				if (conf_status_byte_offset < 0)
281 					usage++;
282             }
283             else if (!strcmp(arg, "-b") || !strcmp(arg, "--block-pages")) {
284                 if (++iarg >= argc)
285 					usage++;
286                 else if (sscanf(argv[iarg], "%i", &conf_pages_per_block) < 1)
287 					usage++;
288 				if (conf_pages_per_block < 2)
289 					usage++;
290             }
291             else if (!strcmp(arg, "-t") || !strcmp(arg, "--total-blocks")) {
292                 if (++iarg >= argc)
293 					usage++;
294                 else if (sscanf(argv[iarg], "%i", &conf_total_blocks) < 1)
295 					usage++;
296 				if (conf_total_blocks < 2)
297 					usage++;
298             }
299             else if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) {
300 				conf_verbose_mode++;
301             }
302             else if (!strcmp(arg, "-m") || !strcmp(arg, "--mount")) {
303 				if (++iarg > argc)
304 					usage++;
305 				else if (parse_mount_point(argv[iarg], m_idx) < 0)
306 					usage++;
307 				m_idx++;
308             }
309 			else if (!strcmp(arg, "-e") || !strcmp(arg, "--exec")) {
310 				if (++iarg > argc)
311 					usage++;
312 				else {
313 					sprintf(script_command, "script %s", argv[iarg]);
314 					conf_exec_script = 1;
315 				}
316 			}
317 			else if (!strcmp(arg, "-x") || !strcmp(arg, "--ecc-option")) {
318 				if (++iarg > argc)
319 					usage++;
320 				else {
321 					for (i = 0; i < ARRAY_SIZE(g_ecc_option_strings); i++) {
322 						if (!strcmp(argv[iarg], g_ecc_option_strings[i])) {
323 							conf_ecc_option = i;
324 							break;
325 						}
326 					}
327 					if (i == ARRAY_SIZE(g_ecc_option_strings)) {
328 						MSGLN("ERROR: Invalid ECC option");
329 						usage++;
330 					}
331 				}
332 			}
333 			else if (!strcmp(arg, "-z") || !strcmp(arg, "--ecc-size")) {
334                 if (++iarg >= argc)
335 					usage++;
336                 else if (sscanf(argv[iarg], "%i", &conf_ecc_size) < 1)
337 					usage++;
338 				if (conf_ecc_size < 0 || conf_ecc_size > UFFS_MAX_ECC_SIZE) {
339 					MSGLN("ERROR: Invalid ecc size");
340 					usage++;
341 				}
342 			}
343             else {
344                 MSGLN("Unknown option: %s, try %s --help", arg, argv[0]);
345 				return -1;
346             }
347         }
348         else {
349             MSGLN("Unexpected parameter: %s, try %s --help", arg, argv[0]);
350 			return -1;
351         }
352     }
353 
354     if (usage) {
355         MSGLN("Usage: %s [options]", argv[0]);
356         MSGLN("  -h  --help                                show usage");
357         MSGLN("  -c  --command-line                        command line mode");
358         MSGLN("  -v  --verbose                             verbose mode");
359         MSGLN("  -f  --file           <file>               uffs image file");
360         MSGLN("  -p  --page-size      <n>                  page data size, default=%d", PAGE_DATA_SIZE_DEFAULT);
361         MSGLN("  -s  --spare-size     <n>                  page spare size, default=%d", PAGE_SPARE_SIZE_DEFAULT);
362 		MSGLN("  -o  --status-offset  <n>                  status byte offset, default=%d", STATUS_BYTE_OFFSET_DEFAULT);
363         MSGLN("  -b  --block-pages    <n>                  pages per block, default=%d", PAGES_PER_BLOCK_DEFAULT);
364         MSGLN("  -t  --total-blocks   <n>                  total blocks");
365         MSGLN("  -m  --mount          <mount_point,start,end> , for example: -m /,0,-1");
366 		MSGLN("  -x  --ecc-option     <none|soft|hw|auto>  ECC option, default=%s", g_ecc_option_strings[ECC_OPTION_DEFAULT]);
367 		MSGLN("  -z  --ecc-size       <n>                  ECC size, default=0 (auto)");
368         MSGLN("  -e  --exec           <file>               execute a script file");
369         MSGLN("");
370 
371         return -1;
372     }
373 
374 	if (m_idx == 0) {
375 		// if not given mount information, use default ('/' for whole partition)
376 		parse_mount_point("/,0,-1", 0);
377 	}
378 
379 	return 0;
380 }
381 
382 
print_mount_points(void)383 static void print_mount_points(void)
384 {
385 	struct uffs_MountTableEntrySt *m;
386 
387 	m = &(conf_mounts[0]);
388 	while (m->dev) {
389 		MSGLN ("Mount point: %s, start: %d, end: %d", m->mount, m->start_block, m->end_block);
390 		m++;
391 	}
392 }
393 
print_params(void)394 static void print_params(void)
395 {
396 	MSGLN("Parameters summary:");
397 	MSGLN("  uffs image file: %s", conf_emu_filename);
398 	MSGLN("  page size: %d", conf_page_data_size);
399 	MSGLN("  page spare size: %d", conf_page_spare_size);
400 	MSGLN("  pages per block: %d", conf_pages_per_block);
401 	MSGLN("  total blocks: %d", conf_total_blocks);
402 	MSGLN("  ecc option: %d (%s)", conf_ecc_option, g_ecc_option_strings[conf_ecc_option]);
403 	MSGLN("  ecc size: %d%s", conf_ecc_size, conf_ecc_size == 0 ? " (auto)" : "");
404 	MSGLN("  bad block status offset: %d", conf_status_byte_offset);
405 	MSGLN("");
406 }
407 
408 #ifdef UNIX
409 #include <execinfo.h>
410 #include <signal.h>
crash_handler(int sig)411 void crash_handler(int sig)
412 {
413   void *array[10];
414   size_t size;
415 
416   // get void*'s for all entries on the stack
417   size = backtrace(array, 10);
418 
419   // print out all the frames to stderr
420   fprintf(stderr, "Error: signal %d:\n", sig);
421   backtrace_symbols_fd(array, size, 2);
422   exit(1);
423 }
424 #endif
425 
main(int argc,char * argv[])426 int main(int argc, char *argv[])
427 {
428 	int ret;
429 
430 #ifdef UNIX
431 	signal(SIGSEGV, crash_handler);
432 #endif
433 
434 	uffs_SetupDebugOutput(); 	// setup debug output as early as possible
435 
436 	if (parse_options(argc, argv) < 0) {
437 		return -1;
438 	}
439 
440 	if (conf_verbose_mode) {
441 		#if 1
442 		MSGLN("Internal data structure size:");
443 		MSGLN("  TreeNode: %d", sizeof(TreeNode));
444 		MSGLN("  struct BlockListSt: %d", sizeof(struct BlockListSt));
445 		MSGLN("  struct DirhSt: %d", sizeof(struct DirhSt));
446 		MSGLN("  struct FilehSt: %d", sizeof(struct FilehSt));
447 		MSGLN("  struct FdataSt: %d", sizeof(struct FdataSt));
448 		MSGLN("  struct uffs_TagStoreSt: %d", sizeof(struct uffs_TagStoreSt));
449 		MSGLN("  uffs_Buf: %d", sizeof(uffs_Buf));
450 		MSGLN("  struct uffs_BlockInfoSt: %d", sizeof(struct uffs_BlockInfoSt));
451 		MSGLN("");
452 		#endif
453 		print_params();
454 		print_mount_points();
455 	}
456 
457 	// setup file emulator storage with parameters from command line
458 	setup_storage(femu_GetStorage());
459 
460 	// setup file emulator private data
461 	setup_emu_private(femu_GetPrivate());
462 
463 	ret = init_uffs_fs();
464 	if (ret != 0) {
465 		MSGLN ("Init file system fail: %d", ret);
466 		return -1;
467 	}
468 
469 	cli_add_commandset(get_helper_cmds());
470 	cli_add_commandset(get_test_cmds());
471 	if (conf_command_line_mode) {
472 		if (conf_exec_script) {
473 			cli_interpret(script_command);
474 		}
475 		cli_main_entry();
476 	}
477 	else {
478 		if (conf_exec_script) {
479 			cli_interpret(script_command);
480 		}
481 		else {
482 			cli_main_entry();
483 		}
484 	}
485 
486 	release_uffs_fs();
487 
488 	return 0;
489 }
490 #endif
491 
492 
493 
494