1 //==========================================================================
5 // RedBoot fileio support
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002, 2003, 2004 Gary Thomas
13 // Copyright (C) 2004, 2005, 2006 eCosCentric Limited.
15 // eCos is free software; you can redistribute it and/or modify it under
16 // the terms of the GNU General Public License as published by the Free
17 // Software Foundation; either version 2 or (at your option) any later version.
19 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
20 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 // You should have received a copy of the GNU General Public License along
25 // with eCos; if not, write to the Free Software Foundation, Inc.,
26 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 // As a special exception, if other files instantiate templates or use macros
29 // or inline functions from this file, or you compile this file and link it
30 // with other works to produce a work based on this file, this file does not
31 // by itself cause the resulting work to be covered by the GNU General Public
32 // License. However the source code for this file must still be made available
33 // in accordance with section (3) of the GNU General Public License.
35 // This exception does not invalidate any other reasons why a work based on
36 // this file might be covered by the GNU General Public License.
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: dwmw2, msalter
49 // This code is part of RedBoot (tm).
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 // Shoot me. But I don't want struct timeval because redboot provides it.
66 #ifdef CYGPKG_IO_FLASH
67 #include <pkgconf/io_flash.h>
68 #include <cyg/io/io.h>
69 #include <cyg/io/flash.h>
70 #include <cyg/io/config_keys.h>
72 #include <cyg/io/devtab.h>
73 #include <cyg/fileio/fileio.h>
74 #include <cyg/infra/cyg_ass.h> // assertion macros
76 //==========================================================================
78 // Define table boundaries
79 CYG_HAL_TABLE_BEGIN( __FS_cmds_TAB__, FS_cmds);
80 CYG_HAL_TABLE_END( __FS_cmds_TAB_END__, FS_cmds);
82 extern struct cmd __FS_cmds_TAB__[], __FS_cmds_TAB_END__;
84 //==========================================================================
89 diag_printf("*** invalid 'fs' command: %s\n", why);
90 cmd_usage(__FS_cmds_TAB__, &__FS_cmds_TAB_END__, "fs ");
94 //==========================================================================
98 static int mount_count = 0;
102 char dev_str[PATH_MAX];
103 char mp_str[PATH_MAX];
104 char type_str[PATH_MAX];
105 } mounts[MAX_MOUNTS];
107 //==========================================================================
109 static void do_mount(int argc, char *argv[]);
110 static void do_umount(int argc, char *argv[]);
112 /* Temporary hack until flashv2 merged to trunk. We can't tell whether we're
113 * working with flash v1 or v2 from the package version. So if legacy device isn't
114 * defined we check whether, if there is a block device, there's a tell-tale define
115 * that only exists with the v1 version.
117 #if !defined(CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY) && \
118 defined(CYGPKG_IO_FLASH_BLOCK_DEVICE) && \
119 defined(CYGINT_IO_FLASH_BLOCK_CFG_1)
120 # define CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY 1
123 #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
124 #define FLASHPART "[-f <partition>] "
129 local_cmd_entry("mount",
131 FLASHPART "[-d <device>] -t <fstype> [<mountpoint>]",
135 local_cmd_entry("umount",
136 "Unmount file system",
142 //==========================================================================
144 // Mount disk/filesystem
146 do_mount(int argc, char *argv[])
148 char *dev_str = "<undefined>", *type_str, *mp_str;
149 bool dev_set = false, type_set = false;
150 struct option_info opts[3];
151 int err, num_opts = 2;
152 int i,m=0; /* Set to 0 to silence warning */
153 #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
155 bool part_set = false;
158 init_opts(&opts[0], 'd', true, OPTION_ARG_TYPE_STR,
159 (void *)&dev_str, &dev_set, "device");
160 init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_STR,
161 (void *)&type_str, &type_set, "fstype");
162 #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
163 init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_STR,
164 (void *)&part_str, &part_set, "partition");
168 CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options");
170 if (!scan_opts(argc, argv, 1, opts, num_opts, &mp_str, OPTION_ARG_TYPE_STR, "mountpoint"))
174 err_printf("fs mount: Must specify file system type\n");
181 if( mount_count >= MAX_MOUNTS )
183 err_printf("fs mount: Maximum number of mounts exceeded\n");
187 #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
192 if (dev_set && strcmp(dev_str, CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1)) {
193 err_printf("fs mount: May only set one of <device> or <partition>\n");
197 dev_str = CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1;
198 len = (cyg_uint32)strlen(part_str);
200 err = cyg_io_lookup(dev_str, &h);
202 err_printf("fs mount: cyg_io_lookup of \"%s\" returned %d\n", dev_str, err);
205 err = cyg_io_set_config(h, CYG_IO_SET_CONFIG_FLASH_FIS_NAME,
208 diag_printf("fs mount: FIS partition \"%s\" not found\n",
215 for( i = 0; i < MAX_MOUNTS; i++ )
217 if( mounts[i].mp_str[0] != '\0' )
219 if( strcmp(mounts[i].dev_str, dev_str ) == 0 )
221 err_printf("fs mount: Device %s already mounted\n",dev_str);
229 strcpy( mounts[m].mp_str, mp_str );
230 strcpy( mounts[m].dev_str, dev_str );
231 strcpy( mounts[m].type_str, type_str );
233 err = mount(mounts[m].dev_str, mounts[m].mp_str, mounts[m].type_str);
237 err_printf("fs mount: mount(%s,%s,%s) failed %d\n", dev_str, mp_str, type_str, errno);
238 mounts[m].mp_str[0] = '\0'; // mount failed so don't let it appear mounted
242 if( mount_count == 0 )
248 //==========================================================================
251 do_umount(int argc, char *argv[])
257 if( mount_count == 0 )
259 err_printf("fs: No filesystems mounted\n");
263 if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "mountpoint"))
269 for( i = 0; i < MAX_MOUNTS; i++ )
271 if( strcmp(mounts[i].mp_str, dir_str ) == 0 )
275 if( i == MAX_MOUNTS )
277 err_printf("fs unmount: unknown mountpoint %s\n",dir_str);
281 err = umount (dir_str);
284 err_printf("fs umount: unmount failed %d\n", errno);
287 mounts[i].mp_str[0] = '\0';
289 if( mount_count == 0 )
295 //==========================================================================
299 static char rwx[8][4] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" };
302 do_list(int argc, char * argv[])
306 char filename[PATH_MAX];
311 if( mount_count == 0 )
313 err_printf("fs: No filesystems mounted\n");
317 if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
322 dir_str = getcwd(cwd, sizeof(cwd));
325 dirp = opendir(dir_str);
327 err_printf("fs list: no such directory %s\n",dir_str);
332 struct dirent *entry = readdir(dirp);
337 strcpy(filename, dir_str);
338 strcat(filename, "/");
339 strcat(filename, entry->d_name);
341 err = stat(filename, &sbuf);
343 diag_printf("Unable to stat file %s\n", filename);
346 diag_printf("%4d ", sbuf.st_ino);
347 if (S_ISDIR(sbuf.st_mode)) diag_printf("d");
348 if (S_ISCHR(sbuf.st_mode)) diag_printf("c");
349 if (S_ISBLK(sbuf.st_mode)) diag_printf("b");
350 if (S_ISREG(sbuf.st_mode)) diag_printf("-");
351 if (S_ISLNK(sbuf.st_mode)) diag_printf("l");
352 diag_printf("%s%s%s", // Ho, humm, have to hard code the shifts
353 rwx[(sbuf.st_mode & S_IRWXU) >> 16],
354 rwx[(sbuf.st_mode & S_IRWXG) >> 19],
355 rwx[(sbuf.st_mode & S_IRWXO) >> 22]);
356 diag_printf(" %2d size %6d %s\n",
357 sbuf.st_nlink,(int)sbuf.st_size,
365 local_cmd_entry("list",
366 "list directory contents",
373 //==========================================================================
377 do_mkdir(int argc, char * argv[])
382 if( mount_count == 0 )
384 err_printf("fs: No filesystems mounted\n");
388 if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
391 fs_usage("invalid arguments");
395 err = mkdir( dir_str, 0 );
398 err_printf("fs mkdir: failed to create directory %s\n",dir_str);
401 local_cmd_entry("mkdir",
408 //==========================================================================
411 do_deldir(int argc, char * argv[])
416 if( mount_count == 0 )
418 err_printf("fs: No filesystems mounted\n");
422 if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
425 fs_usage("invalid arguments");
429 err = rmdir( dir_str );
432 err_printf("fs deldir: failed to remove directory %s\n",dir_str);
435 local_cmd_entry("deldir",
442 //==========================================================================
445 do_del(int argc, char * argv[])
447 char *name_str = NULL;
450 if( mount_count == 0 )
452 err_printf("fs: No filesystems mounted\n");
456 if (!scan_opts(argc, argv, 1, NULL, 0, &name_str, OPTION_ARG_TYPE_STR, "file") ||
459 fs_usage("invalid arguments");
463 err = unlink( name_str );
466 err_printf("fs del: failed to delete file %s\n",name_str);
469 local_cmd_entry("del",
476 //==========================================================================
479 do_move(int argc, char * argv[])
482 __externC int rename( const char *oldname, const char *newname );
483 if( mount_count == 0 )
485 err_printf("fs: No filesystems mounted\n");
490 fs_usage("bad arguments to move command\n");
492 err = rename( argv[1], argv[2] );
495 err_printf("fs move: failed to move file %s to %s\n",argv[1],argv[2]);
498 local_cmd_entry("move",
505 //==========================================================================
508 do_cd(int argc, char * argv[])
513 if( mount_count == 0 )
515 err_printf("fs: No filesystems mounted\n");
519 if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
522 if( dir_str == NULL )
525 err = chdir( dir_str );
528 err_printf("fs cd: failed to change directory %s\n",dir_str);
531 local_cmd_entry("cd",
538 //==========================================================================
541 do_write(int argc, char * argv[])
543 char *name_str = NULL;
545 struct option_info opts[2];
546 CYG_ADDRESS mem_addr = 0;
547 unsigned long length = 0;
548 bool mem_addr_set = false;
549 bool length_set = false;
552 if( mount_count == 0 )
554 err_printf("fs: No filesystems mounted\n");
558 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
559 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
560 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
561 (void *)&length, (bool *)&length_set, "image length");
563 if (!scan_opts(argc, argv, 1, opts, 2, &name_str, OPTION_ARG_TYPE_STR, "file name") ||
566 fs_usage("invalid arguments");
570 // diag_printf("load_address %08x %08x\n",load_address,load_address_end);
571 // diag_printf("ram %08x %08x\n",ram_start, ram_end);
572 // diag_printf("file name %08x >%s<\n",name_str,name_str);
575 (load_address >= (CYG_ADDRESS)ram_start) &&
576 ((load_address_end) < (CYG_ADDRESS)ram_end))
578 mem_addr = load_address;
582 length = load_address_end - load_address;
584 // maybe get length from existing file size if no loaded
589 fd = open( name_str, O_WRONLY|O_CREAT|O_TRUNC );
593 err_printf("fs write: Cannot open %s\n", name_str );
597 // diag_printf("write %08x %08x\n",mem_addr, length );
599 err = write( fd, (void *)mem_addr, length );
603 err_printf("fs write: failed to write to file %d(%d) %d\n",err,length,errno);
609 err_printf("fs write: close failed\n");
612 local_cmd_entry("write",
613 "write data to file",
614 "-b <mem_base> -l <image_length> <file_name>",
619 //==========================================================================
621 __externC cyg_fstab_entry cyg_fstab[];
622 __externC cyg_fstab_entry cyg_fstab_end;
623 __externC cyg_mtab_entry cyg_mtab[];
624 __externC cyg_mtab_entry cyg_mtab_end;
627 do_info(int argc, char * argv[])
629 cyg_bool found = false;
631 cyg_devtab_entry_t *t;
633 for( f = &cyg_fstab[0] ; f != &cyg_fstab_end; f++ )
637 diag_printf("Filesystems available:\n");
640 diag_printf("%s\n",f->name);
644 for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
646 if( (t->status & CYG_DEVTAB_STATUS_BLOCK) == 0 ||
647 (t->status & CYG_DEVTAB_STATUS_AVAIL) == 0 )
652 diag_printf("\nDevices available:\n");
655 diag_printf("%s\n",t->name);
658 if( mount_count != 0 )
662 diag_printf("\nMounted filesystems:\n");
663 diag_printf(" Device Filesystem Mounted on\n");
665 for( i = 0; i < MAX_MOUNTS; i++ )
667 if( mounts[i].mp_str[0] != '\0' )
668 diag_printf("%32s %10s %s\n", mounts[i].dev_str, mounts[i].type_str, mounts[i].mp_str);
673 local_cmd_entry("info",
680 //==========================================================================
683 do_fs(int argc, char *argv[])
688 fs_usage("too few arguments");
691 if ((cmd = cmd_search(__FS_cmds_TAB__, &__FS_cmds_TAB_END__,
692 argv[1])) != (struct cmd *)0) {
693 (cmd->fun)(argc-1, argv+1);
696 fs_usage("unrecognized command");
699 RedBoot_nested_cmd("fs",
700 "Manage Filesystem files",
703 __FS_cmds_TAB__, &__FS_cmds_TAB_END__
707 //==========================================================================
712 fileio_stream_open(connection_info_t *info, int *err)
714 char *filename = info->filename;
716 if( mount_count == 0 )
718 diag_printf("fs: No filesystems mounted\n");
722 fd = open(filename, O_RDONLY);
724 diag_printf("fs: Open failed, error %d\n", errno);
731 fileio_stream_read(char *buf, int size, int *err)
735 if ((nread = read(fd, buf, size)) < 0) {
743 fileio_stream_close(int *err)
749 fileio_error(int err)
751 static char myerr[10];
753 diag_sprintf(myerr, "error %d", err);
760 GETC_IO_FUNCS(fileio_io, fileio_stream_open, fileio_stream_close,
761 0, fileio_stream_read, fileio_error);
762 RedBoot_load(file, fileio_io, true, true, 0);
764 //==========================================================================