// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2002, 2003, 2004 Gary Thomas
+// Copyright (C) 2004, 2005, 2006 eCosCentric Limited.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
-// Author(s): dwmw2, msalter
-// Date: 2003-11-27
+// Author(s): nickg
+// Contributors: dwmw2, msalter
+// Date: 2004-11-21
// Purpose:
// Description:
//
#include <unistd.h>
#include <string.h>
#ifdef CYGPKG_IO_FLASH
+#include <pkgconf/io_flash.h>
#include <cyg/io/io.h>
#include <cyg/io/flash.h>
#include <cyg/io/config_keys.h>
#endif
+#include <cyg/io/devtab.h>
#include <cyg/fileio/fileio.h>
#include <cyg/infra/cyg_ass.h> // assertion macros
+//==========================================================================
+
+// Define table boundaries
+CYG_HAL_TABLE_BEGIN( __FS_cmds_TAB__, FS_cmds);
+CYG_HAL_TABLE_END( __FS_cmds_TAB_END__, FS_cmds);
+
+extern struct cmd __FS_cmds_TAB__[], __FS_cmds_TAB_END__;
+
+//==========================================================================
+
+static void
+fs_usage(char *why)
+{
+ diag_printf("*** invalid 'fs' command: %s\n", why);
+ cmd_usage(__FS_cmds_TAB__, &__FS_cmds_TAB_END__, "fs ");
+}
+
+
+//==========================================================================
+
+#define MAX_MOUNTS 4
+
+static int mount_count = 0;
+
+static struct
+{
+ char dev_str[PATH_MAX];
+ char mp_str[PATH_MAX];
+ char type_str[PATH_MAX];
+} mounts[MAX_MOUNTS];
+
+//==========================================================================
+
static void do_mount(int argc, char *argv[]);
static void do_umount(int argc, char *argv[]);
-#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE
+/* Temporary hack until flashv2 merged to trunk. We can't tell whether we're
+ * working with flash v1 or v2 from the package version. So if legacy device isn't
+ * defined we check whether, if there is a block device, there's a tell-tale define
+ * that only exists with the v1 version.
+ */
+#if !defined(CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY) && \
+ defined(CYGPKG_IO_FLASH_BLOCK_DEVICE) && \
+ defined(CYGINT_IO_FLASH_BLOCK_CFG_1)
+# define CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY 1
+#endif
+
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
#define FLASHPART "[-f <partition>] "
#else
#define FLASHPART
#endif
-RedBoot_cmd("mount",
- "Mount file system",
- FLASHPART "[-d <device>] -t fstype",
- do_mount
+local_cmd_entry("mount",
+ "Mount file system",
+ FLASHPART "[-d <device>] -t <fstype> [<mountpoint>]",
+ do_mount,
+ FS_cmds
);
-RedBoot_cmd("umount",
- "Unmount file system",
- "",
- do_umount
+local_cmd_entry("umount",
+ "Unmount file system",
+ "<mountpoint>",
+ do_umount,
+ FS_cmds
);
-int fileio_mounted = 0;
+//==========================================================================
// Mount disk/filesystem
static void
do_mount(int argc, char *argv[])
{
- char *part_str, *dev_str, *type_str;
- bool part_set = false, dev_set = false, type_set = false;
+ char *dev_str = "<undefined>", *type_str, *mp_str;
+ bool dev_set = false, type_set = false;
struct option_info opts[3];
int err, num_opts = 2;
+ int i,m=0; /* Set to 0 to silence warning */
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
+ char *part_str;
+ bool part_set = false;
+#endif
init_opts(&opts[0], 'd', true, OPTION_ARG_TYPE_STR,
(void *)&dev_str, &dev_set, "device");
init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_STR,
(void *)&type_str, &type_set, "fstype");
-#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_STR,
(void *)&part_str, &part_set, "partition");
num_opts++;
CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options");
- if (!scan_opts(argc, argv, 1, opts, num_opts, NULL, 0, NULL))
+ if (!scan_opts(argc, argv, 1, opts, num_opts, &mp_str, OPTION_ARG_TYPE_STR, "mountpoint"))
return;
if (!type_set) {
- diag_printf("Must specify file system type\n");
+ err_printf("fs mount: Must specify file system type\n");
return;
}
- if (fileio_mounted) {
- diag_printf("A file system is already mounted\n");
+
+ if( mp_str == 0 )
+ mp_str = "/";
+
+ if( mount_count >= MAX_MOUNTS )
+ {
+ err_printf("fs mount: Maximum number of mounts exceeded\n");
return;
}
-#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE
+
+#ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
if (part_set) {
- int len;
+ cyg_uint32 len;
cyg_io_handle_t h;
if (dev_set && strcmp(dev_str, CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1)) {
- diag_printf("May only set one of <device> or <partition>\n");
+ err_printf("fs mount: May only set one of <device> or <partition>\n");
return;
}
dev_str = CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1;
- len = strlen(part_str);
+ len = (cyg_uint32)strlen(part_str);
err = cyg_io_lookup(dev_str, &h);
if (err < 0) {
- diag_printf("cyg_io_lookup of \"%s\" returned %d\n", err);
+ err_printf("fs mount: cyg_io_lookup of \"%s\" returned %d\n", dev_str, err);
return;
}
err = cyg_io_set_config(h, CYG_IO_SET_CONFIG_FLASH_FIS_NAME,
part_str, &len);
if (err < 0) {
- diag_printf("FIS partition \"%s\" not found\n",
+ diag_printf("fs mount: FIS partition \"%s\" not found\n",
part_str);
return;
}
}
#endif
- err = mount(dev_str, "/", type_str);
-
- if (err) {
- diag_printf("Mount failed %d\n", err);
- } else {
-// diag_printf("Mount %s file system succeeded\n", type_str);
- fileio_mounted = 1;
-#ifdef CYGBLD_REDBOOT_FILEIO_WITH_LS
- chdir("/");
-#endif
+
+ for( i = 0; i < MAX_MOUNTS; i++ )
+ {
+ if( mounts[i].mp_str[0] != '\0' )
+ {
+ if( strcmp(mounts[i].dev_str, dev_str ) == 0 )
+ {
+ err_printf("fs mount: Device %s already mounted\n",dev_str);
+ return;
+ }
+ }
+ else
+ m = i;
+ }
+
+ strcpy( mounts[m].mp_str, mp_str );
+ strcpy( mounts[m].dev_str, dev_str );
+ strcpy( mounts[m].type_str, type_str );
+
+ err = mount(mounts[m].dev_str, mounts[m].mp_str, mounts[m].type_str);
+
+ if (err)
+ {
+ err_printf("fs mount: mount(%s,%s,%s) failed %d\n", dev_str, mp_str, type_str, errno);
+ mounts[m].mp_str[0] = '\0'; // mount failed so don't let it appear mounted
+ }
+ else
+ {
+ if( mount_count == 0 )
+ chdir( "/" );
+ mount_count++;
}
}
+//==========================================================================
+
static void
do_umount(int argc, char *argv[])
{
- if (!fileio_mounted) {
+ char *dir_str;
+ int err;
+ int i;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "mountpoint"))
return;
+
+ if( dir_str == 0 )
+ dir_str = "/";
+
+ for( i = 0; i < MAX_MOUNTS; i++ )
+ {
+ if( strcmp(mounts[i].mp_str, dir_str ) == 0 )
+ break;
+ }
+
+ if( i == MAX_MOUNTS )
+ {
+ err_printf("fs unmount: unknown mountpoint %s\n",dir_str);
+ return;
+ }
+
+ err = umount (dir_str);
+
+ if (err)
+ err_printf("fs umount: unmount failed %d\n", errno);
+ else
+ {
+ mounts[i].mp_str[0] = '\0';
+ mount_count--;
+ if( mount_count == 0 )
+ chdir( "/" );
}
- umount ("/");
- fileio_mounted = 0;
+
}
-#ifdef CYGBLD_REDBOOT_FILEIO_WITH_LS
+//==========================================================================
+
#include <dirent.h>
static char rwx[8][4] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" };
static void
-do_ls(int argc, char * argv[])
+do_list(int argc, char * argv[])
{
char * dir_str;
- struct option_info opts[1];
- bool dir_set = false;
DIR *dirp;
- char cwd[PATH_MAX];
char filename[PATH_MAX];
+ char cwd[PATH_MAX];
struct stat sbuf;
int err;
-
- init_opts(&opts[0], 'd', true, OPTION_ARG_TYPE_STR,
- (void *)&dir_str, &dir_set, "directory");
-
- if (!fileio_mounted) {
- diag_printf("No filesystem mounted\n");
- return;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
}
- if (!scan_opts(argc, argv, 1, opts, 1, NULL, 0, NULL))
+ if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
return;
- if (!dir_set) {
- getcwd(cwd,sizeof(cwd));
- dir_str = cwd;
+ if( dir_str == 0 )
+ {
+ dir_str = getcwd(cwd, sizeof(cwd));
}
- diag_printf("directory %s\n",dir_str);
dirp = opendir(dir_str);
if (dirp==NULL) {
- diag_printf("no such directory %s\n",dir_str);
+ err_printf("fs list: no such directory %s\n",dir_str);
return;
}
rwx[(sbuf.st_mode & S_IRWXG) >> 19],
rwx[(sbuf.st_mode & S_IRWXO) >> 22]);
diag_printf(" %2d size %6d %s\n",
- sbuf.st_nlink,sbuf.st_size,
+ sbuf.st_nlink,(int)sbuf.st_size,
entry->d_name);
}
return;
}
-RedBoot_cmd("ls",
- "list directory contents",
- "[-d directory]",
- do_ls
+local_cmd_entry("list",
+ "list directory contents",
+ "[<directory>]",
+ do_list,
+ FS_cmds
+ );
+
+
+//==========================================================================
+
+
+static void
+do_mkdir(int argc, char * argv[])
+{
+ char *dir_str;
+ int err;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
+ dir_str == NULL)
+ {
+ fs_usage("invalid arguments");
+ return;
+ }
+
+ err = mkdir( dir_str, 0 );
+
+ if( err != 0 )
+ err_printf("fs mkdir: failed to create directory %s\n",dir_str);
+}
+
+local_cmd_entry("mkdir",
+ "create directory",
+ "<directory>",
+ do_mkdir,
+ FS_cmds
+ );
+
+//==========================================================================
+
+static void
+do_deldir(int argc, char * argv[])
+{
+ char *dir_str;
+ int err;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
+ dir_str == NULL)
+ {
+ fs_usage("invalid arguments");
+ return;
+ }
+
+ err = rmdir( dir_str );
+
+ if( err != 0 )
+ err_printf("fs deldir: failed to remove directory %s\n",dir_str);
+}
+
+local_cmd_entry("deldir",
+ "delete directory",
+ "<directory>",
+ do_deldir,
+ FS_cmds
+ );
+
+//==========================================================================
+
+static void
+do_del(int argc, char * argv[])
+{
+ char *name_str = NULL;
+ int err;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ if (!scan_opts(argc, argv, 1, NULL, 0, &name_str, OPTION_ARG_TYPE_STR, "file") ||
+ name_str == NULL)
+ {
+ fs_usage("invalid arguments");
+ return;
+ }
+
+ err = unlink( name_str );
+
+ if( err != 0 )
+ err_printf("fs del: failed to delete file %s\n",name_str);
+}
+
+local_cmd_entry("del",
+ "delete file",
+ "<file>",
+ do_del,
+ FS_cmds
+ );
+
+//==========================================================================
+
+static void
+do_move(int argc, char * argv[])
+{
+ int err;
+ __externC int rename( const char *oldname, const char *newname );
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ if( argc != 3 )
+ fs_usage("bad arguments to move command\n");
+
+ err = rename( argv[1], argv[2] );
+
+ if( err != 0 )
+ err_printf("fs move: failed to move file %s to %s\n",argv[1],argv[2]);
+}
+
+local_cmd_entry("move",
+ "move file",
+ "<from> <to>",
+ do_move,
+ FS_cmds
+ );
+
+//==========================================================================
+
+static void
+do_cd(int argc, char * argv[])
+{
+ char *dir_str;
+ int err;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
+ return;
+
+ if( dir_str == NULL )
+ dir_str = "/";
+
+ err = chdir( dir_str );
+
+ if( err != 0 )
+ err_printf("fs cd: failed to change directory %s\n",dir_str);
+}
+
+local_cmd_entry("cd",
+ "change directory",
+ "[<directory>]",
+ do_cd,
+ FS_cmds
+ );
+
+//==========================================================================
+
+static void
+do_write(int argc, char * argv[])
+{
+ char *name_str = NULL;
+ int err;
+ struct option_info opts[2];
+ CYG_ADDRESS mem_addr = 0;
+ unsigned long length = 0;
+ bool mem_addr_set = false;
+ bool length_set = false;
+ int fd;
+
+ if( mount_count == 0 )
+ {
+ err_printf("fs: No filesystems mounted\n");
+ return;
+ }
+
+ init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
+ (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
+ init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
+ (void *)&length, (bool *)&length_set, "image length");
+
+ if (!scan_opts(argc, argv, 1, opts, 2, &name_str, OPTION_ARG_TYPE_STR, "file name") ||
+ name_str == NULL)
+ {
+ fs_usage("invalid arguments");
+ return;
+ }
+
+// diag_printf("load_address %08x %08x\n",load_address,load_address_end);
+// diag_printf("ram %08x %08x\n",ram_start, ram_end);
+// diag_printf("file name %08x >%s<\n",name_str,name_str);
+
+ if (!mem_addr_set &&
+ (load_address >= (CYG_ADDRESS)ram_start) &&
+ ((load_address_end) < (CYG_ADDRESS)ram_end))
+ {
+ mem_addr = load_address;
+ mem_addr_set = true;
+ if (!length_set)
+ {
+ length = load_address_end - load_address;
+ length_set = true;
+ // maybe get length from existing file size if no loaded
+ // image?
+ }
+ }
+
+ fd = open( name_str, O_WRONLY|O_CREAT|O_TRUNC );
+
+ if( fd < 0 )
+ {
+ err_printf("fs write: Cannot open %s\n", name_str );
+ return;
+ }
+
+// diag_printf("write %08x %08x\n",mem_addr, length );
+
+ err = write( fd, (void *)mem_addr, length );
+
+ if( err != length )
+ {
+ err_printf("fs write: failed to write to file %d(%d) %d\n",err,length,errno);
+ }
+
+ err = close( fd );
+
+ if( err != 0 )
+ err_printf("fs write: close failed\n");
+}
+
+local_cmd_entry("write",
+ "write data to file",
+ "-b <mem_base> -l <image_length> <file_name>",
+ do_write,
+ FS_cmds
+ );
+
+//==========================================================================
+
+__externC cyg_fstab_entry cyg_fstab[];
+__externC cyg_fstab_entry cyg_fstab_end;
+__externC cyg_mtab_entry cyg_mtab[];
+__externC cyg_mtab_entry cyg_mtab_end;
+
+static void
+do_info(int argc, char * argv[])
+{
+ cyg_bool found = false;
+ cyg_fstab_entry *f;
+ cyg_devtab_entry_t *t;
+
+ for( f = &cyg_fstab[0] ; f != &cyg_fstab_end; f++ )
+ {
+ if( !found )
+ {
+ diag_printf("Filesystems available:\n");
+ found = true;
+ }
+ diag_printf("%s\n",f->name);
+ }
+
+ found = false;
+ for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
+ {
+ if( (t->status & CYG_DEVTAB_STATUS_BLOCK) == 0 ||
+ (t->status & CYG_DEVTAB_STATUS_AVAIL) == 0 )
+ continue;
+
+ if( !found )
+ {
+ diag_printf("\nDevices available:\n");
+ found = true;
+ }
+ diag_printf("%s\n",t->name);
+ }
+
+ if( mount_count != 0 )
+ {
+ int i;
+
+ diag_printf("\nMounted filesystems:\n");
+ diag_printf(" Device Filesystem Mounted on\n");
+
+ for( i = 0; i < MAX_MOUNTS; i++ )
+ {
+ if( mounts[i].mp_str[0] != '\0' )
+ diag_printf("%32s %10s %s\n", mounts[i].dev_str, mounts[i].type_str, mounts[i].mp_str);
+ }
+ }
+}
+
+local_cmd_entry("info",
+ "filesystem info",
+ "",
+ do_info,
+ FS_cmds
);
-#endif // CYGBLD_REDBOOT_FILEIO_WITH_LS
+//==========================================================================
+
+static void
+do_fs(int argc, char *argv[])
+{
+ struct cmd *cmd;
+
+ if (argc < 2) {
+ fs_usage("too few arguments");
+ return;
+ }
+ if ((cmd = cmd_search(__FS_cmds_TAB__, &__FS_cmds_TAB_END__,
+ argv[1])) != (struct cmd *)0) {
+ (cmd->fun)(argc-1, argv+1);
+ return;
+ }
+ fs_usage("unrecognized command");
+}
+
+RedBoot_nested_cmd("fs",
+ "Manage Filesystem files",
+ "{cmds}",
+ do_fs,
+ __FS_cmds_TAB__, &__FS_cmds_TAB_END__
+ );
+
+
+//==========================================================================
+
static int fd;
externC int
{
char *filename = info->filename;
- if (!fileio_mounted) {
- diag_printf("No file system mounted\n");
- return -1;
- }
+ if( mount_count == 0 )
+ {
+ diag_printf("fs: No filesystems mounted\n");
+ return -1;
+ }
+
fd = open(filename, O_RDONLY);
if (fd < 0) {
- diag_printf("Open failed, error %d\n", errno);
+ diag_printf("fs: Open failed, error %d\n", errno);
return -1;
}
return 0;
{
static char myerr[10];
- diag_sprintf(myerr, "error %d\n", err);
+ diag_sprintf(myerr, "error %d", err);
return myerr;
}
0, fileio_stream_read, fileio_error);
RedBoot_load(file, fileio_io, true, true, 0);
+//==========================================================================
+// End of fileio.c
+