]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/redboot/v2_0/src/fs/fileio.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / fs / fileio.c
1 //==========================================================================
2 //
3 //      fileio.c
4 //
5 //      RedBoot fileio support
6 //
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.
14 //
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.
18 //
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
22 // for more details.
23 //
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.
27 //
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.
34 //
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.
37 //
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    nickg
44 // Contributors: dwmw2, msalter
45 // Date:         2004-11-21
46 // Purpose:      
47 // Description:  
48 //              
49 // This code is part of RedBoot (tm).
50 //
51 //####DESCRIPTIONEND####
52 //
53 //==========================================================================
54
55 // Shoot me. But I don't want struct timeval because redboot provides it.
56 #define _POSIX_SOURCE
57 #include <time.h>
58 #undef _POSIX_SOURCE
59
60 #include <redboot.h>
61 #include <errno.h>
62 #include <stdio.h>
63 #include <fcntl.h>
64 #include <unistd.h>
65 #include <string.h>
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>
71 #endif
72 #include <cyg/io/devtab.h>
73 #include <cyg/fileio/fileio.h>
74 #include <cyg/infra/cyg_ass.h>         // assertion macros
75
76 //==========================================================================
77
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);
81
82 extern struct cmd __FS_cmds_TAB__[], __FS_cmds_TAB_END__;
83
84 //==========================================================================
85
86 static void
87 fs_usage(char *why)
88 {
89     diag_printf("*** invalid 'fs' command: %s\n", why);
90     cmd_usage(__FS_cmds_TAB__, &__FS_cmds_TAB_END__, "fs ");
91 }
92
93
94 //==========================================================================
95
96 #define MAX_MOUNTS      4
97
98 static int mount_count = 0;
99
100 static struct
101 {
102     char dev_str[PATH_MAX];
103     char mp_str[PATH_MAX];
104     char type_str[PATH_MAX];
105 } mounts[MAX_MOUNTS];
106
107 //==========================================================================
108
109 static void do_mount(int argc, char *argv[]);
110 static void do_umount(int argc, char *argv[]);
111
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.
116  */
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
121 #endif
122
123 #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
124 #define FLASHPART "[-f <partition>] "
125 #else
126 #define FLASHPART
127 #endif
128
129 local_cmd_entry("mount", 
130                 "Mount file system",
131                 FLASHPART "[-d <device>] -t <fstype> [<mountpoint>]",
132                 do_mount,
133                 FS_cmds
134     );
135 local_cmd_entry("umount", 
136                 "Unmount file system",
137                 "<mountpoint>",
138                 do_umount,
139                 FS_cmds
140     );
141
142 //==========================================================================
143
144 // Mount disk/filesystem
145 static void
146 do_mount(int argc, char *argv[])
147 {
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
154     char *part_str;
155     bool part_set = false;
156 #endif
157
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");
165     num_opts++;
166 #endif
167
168     CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options");
169
170     if (!scan_opts(argc, argv, 1, opts, num_opts, &mp_str, OPTION_ARG_TYPE_STR, "mountpoint"))
171         return;
172
173     if (!type_set) {
174         err_printf("fs mount: Must specify file system type\n");
175         return;
176     }
177
178     if( mp_str == 0 )
179         mp_str = "/";
180
181     if( mount_count >= MAX_MOUNTS )
182     {
183         err_printf("fs mount: Maximum number of mounts exceeded\n");
184         return;
185     }
186     
187 #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY
188     if (part_set) {
189         cyg_uint32 len;
190         cyg_io_handle_t h;
191
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");
194             return;
195         }
196
197         dev_str = CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1;
198         len = (cyg_uint32)strlen(part_str);
199
200         err = cyg_io_lookup(dev_str, &h);
201         if (err < 0) {
202             err_printf("fs mount: cyg_io_lookup of \"%s\" returned %d\n", dev_str, err);
203             return;
204         }
205         err = cyg_io_set_config(h, CYG_IO_SET_CONFIG_FLASH_FIS_NAME,
206                                 part_str, &len);
207         if (err < 0) {
208             diag_printf("fs mount: FIS partition \"%s\" not found\n",
209                         part_str);
210             return;
211         }
212     }
213 #endif
214
215     for( i = 0; i < MAX_MOUNTS; i++ )
216     {
217         if( mounts[i].mp_str[0] != '\0' )
218         {
219             if( strcmp(mounts[i].dev_str, dev_str ) == 0 )
220             {
221                 err_printf("fs mount: Device %s already mounted\n",dev_str);
222                 return;
223             }
224         }
225         else
226             m = i;
227     }
228
229     strcpy( mounts[m].mp_str, mp_str );
230     strcpy( mounts[m].dev_str, dev_str );
231     strcpy( mounts[m].type_str, type_str );
232     
233     err = mount(mounts[m].dev_str, mounts[m].mp_str, mounts[m].type_str);
234
235     if (err)
236     {
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
239     }
240     else
241     {
242         if( mount_count == 0 )
243             chdir( "/" );
244         mount_count++;
245     }
246 }
247
248 //==========================================================================
249
250 static void
251 do_umount(int argc, char *argv[])
252 {
253     char *dir_str;
254     int err;
255     int i;
256     
257      if( mount_count == 0 )
258      {
259          err_printf("fs: No filesystems mounted\n");
260          return;
261      }
262      
263     if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "mountpoint"))
264         return;
265
266     if( dir_str == 0 )
267         dir_str = "/";
268
269     for( i = 0; i < MAX_MOUNTS; i++ )
270     {
271         if( strcmp(mounts[i].mp_str, dir_str ) == 0 )
272             break;
273     }
274
275     if( i == MAX_MOUNTS )
276     {
277         err_printf("fs unmount: unknown mountpoint %s\n",dir_str);
278         return;
279     }
280     
281     err = umount (dir_str);
282
283     if (err)
284         err_printf("fs umount: unmount failed %d\n", errno);
285     else
286     {
287         mounts[i].mp_str[0] = '\0';
288         mount_count--;
289         if( mount_count == 0 )
290             chdir( "/" );
291     }
292     
293 }
294
295 //==========================================================================
296
297 #include <dirent.h>
298
299 static char rwx[8][4] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" }; 
300
301 static void 
302 do_list(int argc, char * argv[])
303 {
304      char * dir_str;
305      DIR *dirp;
306      char filename[PATH_MAX];
307      char cwd[PATH_MAX];
308      struct stat sbuf;
309      int err;
310
311      if( mount_count == 0 )
312      {
313          err_printf("fs: No filesystems mounted\n");
314          return;
315      }
316      
317      if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
318           return;
319
320      if( dir_str == 0 )
321      {
322          dir_str = getcwd(cwd, sizeof(cwd));
323      }
324      
325      dirp = opendir(dir_str);
326      if (dirp==NULL) {
327           err_printf("fs list: no such directory %s\n",dir_str);
328           return;
329      }
330      
331      for (;;) {
332           struct dirent *entry = readdir(dirp);
333           
334           if( entry == NULL )
335                break;
336     
337           strcpy(filename, dir_str);
338           strcat(filename, "/");
339           strcat(filename, entry->d_name);
340           
341           err = stat(filename, &sbuf);
342           if (err < 0) {
343                diag_printf("Unable to stat file %s\n", filename);
344                continue;
345           }
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, 
358                       entry->d_name);
359      }
360      
361      closedir(dirp);
362      return;
363 }
364
365 local_cmd_entry("list", 
366                 "list directory contents",
367                 "[<directory>]",
368                 do_list,
369                 FS_cmds
370     );
371
372
373 //==========================================================================
374
375
376 static void 
377 do_mkdir(int argc, char * argv[])
378 {
379     char *dir_str;
380     int err;
381     
382      if( mount_count == 0 )
383      {
384          err_printf("fs: No filesystems mounted\n");
385          return;
386      }
387      
388     if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
389         dir_str == NULL)
390     {
391         fs_usage("invalid arguments");
392         return;
393     }
394
395     err = mkdir( dir_str, 0 );
396
397     if( err != 0 )
398         err_printf("fs mkdir: failed to create directory %s\n",dir_str);
399 }
400
401 local_cmd_entry("mkdir", 
402                 "create directory",
403                 "<directory>",
404                 do_mkdir,
405                 FS_cmds
406     );
407
408 //==========================================================================
409
410 static void 
411 do_deldir(int argc, char * argv[])
412 {
413     char *dir_str;
414     int err;
415     
416      if( mount_count == 0 )
417      {
418          err_printf("fs: No filesystems mounted\n");
419          return;
420      }
421      
422     if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory") ||
423         dir_str == NULL)
424     {
425         fs_usage("invalid arguments");
426         return;
427     }
428
429     err = rmdir( dir_str );
430
431     if( err != 0 )
432         err_printf("fs deldir: failed to remove directory %s\n",dir_str);
433 }
434
435 local_cmd_entry("deldir", 
436                 "delete directory",
437                 "<directory>",
438                 do_deldir,
439                 FS_cmds
440     );
441
442 //==========================================================================
443
444 static void 
445 do_del(int argc, char * argv[])
446 {
447     char *name_str = NULL;
448     int err;
449     
450      if( mount_count == 0 )
451      {
452          err_printf("fs: No filesystems mounted\n");
453          return;
454      }
455      
456     if (!scan_opts(argc, argv, 1, NULL, 0, &name_str, OPTION_ARG_TYPE_STR, "file") ||
457         name_str == NULL)
458     {
459         fs_usage("invalid arguments");
460         return;
461     }
462
463     err = unlink( name_str );
464
465     if( err != 0 )
466         err_printf("fs del: failed to delete file %s\n",name_str);
467 }
468
469 local_cmd_entry("del", 
470                 "delete file",
471                 "<file>",
472                 do_del,
473                 FS_cmds
474     );
475
476 //==========================================================================
477
478 static void 
479 do_move(int argc, char * argv[])
480 {
481     int err;
482     __externC int rename( const char *oldname, const char *newname );
483     if( mount_count == 0 )
484     {
485         err_printf("fs: No filesystems mounted\n");
486         return;
487     }
488
489     if( argc != 3 )
490         fs_usage("bad arguments to move command\n");
491
492     err = rename( argv[1], argv[2] );
493
494     if( err != 0 )
495         err_printf("fs move: failed to move file %s to %s\n",argv[1],argv[2]);
496 }
497
498 local_cmd_entry("move", 
499                 "move file",
500                 "<from> <to>",
501                 do_move,
502                 FS_cmds
503     );
504
505 //==========================================================================
506
507 static void 
508 do_cd(int argc, char * argv[])
509 {
510     char *dir_str;
511     int err;
512     
513      if( mount_count == 0 )
514      {
515          err_printf("fs: No filesystems mounted\n");
516          return;
517      }
518      
519     if (!scan_opts(argc, argv, 1, NULL, 0, &dir_str, OPTION_ARG_TYPE_STR, "directory"))
520         return;
521
522     if( dir_str == NULL )
523         dir_str = "/";
524     
525     err = chdir( dir_str );
526
527     if( err != 0 )
528         err_printf("fs cd: failed to change directory %s\n",dir_str);
529 }
530
531 local_cmd_entry("cd", 
532                 "change directory",
533                 "[<directory>]",
534                 do_cd,
535                 FS_cmds
536     );
537
538 //==========================================================================
539
540 static void 
541 do_write(int argc, char * argv[])
542 {
543     char *name_str = NULL;
544     int err;
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;
550     int fd;
551     
552      if( mount_count == 0 )
553      {
554          err_printf("fs: No filesystems mounted\n");
555          return;
556      }
557
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");
562      
563     if (!scan_opts(argc, argv, 1, opts, 2, &name_str, OPTION_ARG_TYPE_STR, "file name") ||
564         name_str == NULL)
565     {
566         fs_usage("invalid arguments");
567         return;
568     }
569
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);
573     
574     if (!mem_addr_set &&
575         (load_address >= (CYG_ADDRESS)ram_start) &&
576         ((load_address_end) < (CYG_ADDRESS)ram_end))
577     {
578         mem_addr = load_address;
579         mem_addr_set = true;
580         if (!length_set)
581         {
582             length = load_address_end - load_address;
583             length_set = true;
584             // maybe get length from existing file size if no loaded
585             // image?
586         }
587     }
588     
589     fd = open( name_str, O_WRONLY|O_CREAT|O_TRUNC );
590
591     if( fd < 0 )
592     {
593         err_printf("fs write: Cannot open %s\n", name_str );
594         return;
595     }
596
597 //    diag_printf("write %08x %08x\n",mem_addr, length );
598     
599     err = write( fd, (void *)mem_addr, length );
600
601     if( err != length )
602     {
603         err_printf("fs write: failed to write to file %d(%d) %d\n",err,length,errno);
604     }
605
606     err = close( fd );
607
608     if( err != 0 )
609         err_printf("fs write: close failed\n");
610 }
611
612 local_cmd_entry("write",
613                 "write data to file",
614                 "-b <mem_base> -l <image_length> <file_name>",
615                 do_write,
616                 FS_cmds
617     );
618
619 //==========================================================================
620
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;
625
626 static void 
627 do_info(int argc, char * argv[])
628 {
629     cyg_bool found = false;
630     cyg_fstab_entry *f;
631     cyg_devtab_entry_t *t;
632
633     for( f = &cyg_fstab[0] ; f != &cyg_fstab_end; f++ )
634     {
635         if( !found )
636         {
637             diag_printf("Filesystems available:\n");
638             found = true;
639         }
640         diag_printf("%s\n",f->name);
641     }
642
643     found = false;
644     for (t = &__DEVTAB__[0]; t != &__DEVTAB_END__; t++)
645     {
646         if( (t->status & CYG_DEVTAB_STATUS_BLOCK) == 0 ||
647             (t->status & CYG_DEVTAB_STATUS_AVAIL) == 0 )
648             continue;
649         
650         if( !found )
651         {
652             diag_printf("\nDevices available:\n");
653             found = true;
654         }
655         diag_printf("%s\n",t->name);
656     }
657
658     if( mount_count != 0 )
659     {
660         int i;
661
662         diag_printf("\nMounted filesystems:\n");
663         diag_printf("            Device               Filesystem Mounted on\n");
664
665         for( i = 0; i < MAX_MOUNTS; i++ )
666         {
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);
669         }
670     }
671 }
672
673 local_cmd_entry("info", 
674                 "filesystem info",
675                 "",
676                 do_info,
677                 FS_cmds
678     );
679
680 //==========================================================================
681
682 static void
683 do_fs(int argc, char *argv[])
684 {
685     struct cmd *cmd;
686
687     if (argc < 2) {
688         fs_usage("too few arguments");
689         return;
690     }
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);
694         return;
695     }
696     fs_usage("unrecognized command");
697 }
698
699 RedBoot_nested_cmd("fs", 
700             "Manage Filesystem files", 
701             "{cmds}",
702             do_fs,
703             __FS_cmds_TAB__, &__FS_cmds_TAB_END__
704     );
705
706
707 //==========================================================================
708
709 static int fd;
710
711 externC int 
712 fileio_stream_open(connection_info_t *info, int *err)
713 {
714     char *filename = info->filename;
715
716      if( mount_count == 0 )
717      {
718          diag_printf("fs: No filesystems mounted\n");
719          return -1;
720      }
721     
722     fd = open(filename, O_RDONLY);
723     if (fd < 0) {
724         diag_printf("fs: Open failed, error %d\n", errno);
725         return -1;
726     }
727     return 0;
728 }
729
730 externC int 
731 fileio_stream_read(char *buf, int size, int *err)
732 {
733     int nread;
734
735     if ((nread = read(fd, buf, size)) < 0) {
736         *err = errno;
737         return -1;
738     }
739     return nread;
740 }
741
742 externC void
743 fileio_stream_close(int *err)
744 {
745     close(fd);
746 }
747
748 externC char *
749 fileio_error(int err)
750 {
751     static char myerr[10];
752
753     diag_sprintf(myerr, "error %d", err);
754     return myerr;
755 }
756
757 //
758 // RedBoot interface
759 //
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);
763
764 //==========================================================================
765 // End of fileio.c
766