source: rtems/testsuites/samples/fileio/init.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 29.9 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2012.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.org/license/LICENSE.
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#define CONFIGURE_INIT
15#include "system.h"
16#include <stdio.h>
17#include <string.h>
18#include <unistd.h>
19#include <stdlib.h>
20#include <errno.h>
21#include <rtems.h>
22#include <fcntl.h>
23#include <inttypes.h>
24#include <rtems/error.h>
25#include <rtems/dosfs.h>
26#include <ctype.h>
27#include <rtems/bdpart.h>
28#include <rtems/libcsupport.h>
29#include <rtems/fsmount.h>
30#include <rtems/ramdisk.h>
31#include <rtems/nvdisk.h>
32#include <rtems/nvdisk-sram.h>
33#include <rtems/shell.h>
34
35const char rtems_test_name[] = "FILE I/O";
36
37#if FILEIO_BUILD
38
39/**
40 * Let the IO system allocation the next available major number.
41 */
42#define RTEMS_DRIVER_AUTO_MAJOR (0)
43
44/*
45 * RAM disk driver so you can create a RAM disk from the shell prompt.
46 */
47/**
48 * The RAM Disk configuration.
49 */
50rtems_ramdisk_config rtems_ramdisk_configuration[] =
51{
52  {
53    block_size: 512,
54    block_num:  1024,
55    location:   NULL
56  }
57};
58
59/**
60 * The number of RAM Disk configurations.
61 */
62size_t rtems_ramdisk_configuration_size = 1;
63
64/**
65 * Create the RAM Disk Driver entry.
66 */
67rtems_driver_address_table rtems_ramdisk_io_ops = {
68  initialization_entry: ramdisk_initialize,
69  open_entry:           rtems_blkdev_generic_open,
70  close_entry:          rtems_blkdev_generic_close,
71  read_entry:           rtems_blkdev_generic_read,
72  write_entry:          rtems_blkdev_generic_write,
73  control_entry:        rtems_blkdev_generic_ioctl
74};
75
76/**
77 * The NV Device descriptor. For this test it is just DRAM.
78 */
79rtems_nvdisk_device_desc rtems_nv_heap_device_descriptor[] =
80{
81  {
82    flags:  0,
83    base:   0,
84    size:   (size_t) 1024 * 1024,
85    nv_ops: &rtems_nvdisk_sram_handlers
86  }
87};
88
89/**
90 * The NV Disk configuration.
91 */
92const rtems_nvdisk_config rtems_nvdisk_configuration[] =
93{
94  {
95    block_size:         512,
96    device_count:       1,
97    devices:            &rtems_nv_heap_device_descriptor[0],
98    flags:              0,
99    info_level:         0
100  }
101};
102
103/**
104 * The number of NV Disk configurations.
105 */
106uint32_t rtems_nvdisk_configuration_size = 1;
107
108/**
109 * Create the NV Disk Driver entry.
110 */
111rtems_driver_address_table rtems_nvdisk_io_ops = {
112  initialization_entry: rtems_nvdisk_initialize,
113  open_entry:           rtems_blkdev_generic_open,
114  close_entry:          rtems_blkdev_generic_close,
115  read_entry:           rtems_blkdev_generic_read,
116  write_entry:          rtems_blkdev_generic_write,
117  control_entry:        rtems_blkdev_generic_ioctl
118};
119
120#if 0
121int
122setup_nvdisk (const char* mntpath)
123{
124  rtems_device_major_number major;
125  rtems_status_code         sc;
126
127  /*
128   * For our test we do not have any static RAM or EEPROM devices so
129   * we allocate the memory from the heap.
130   */
131  rtems_nv_heap_device_descriptor[0].base =
132    malloc (rtems_nv_heap_device_descriptor[0].size);
133
134  if (!rtems_nv_heap_device_descriptor[0].base)
135  {
136    printf ("error: no memory for NV disk\n");
137    return 1;
138  }
139 
140  /*
141   * Register the NV Disk driver.
142   */
143  printf ("Register NV Disk Driver: ");
144  sc = rtems_io_register_driver (RTEMS_DRIVER_AUTO_MAJOR,
145                                 &rtems_nvdisk_io_ops,
146                                 &major);
147  if (sc != RTEMS_SUCCESSFUL)
148  {
149    printf ("error: nvdisk driver not initialised: %s\n",
150            rtems_status_text (sc));
151    return 1;
152  }
153 
154  printf ("successful\n");
155
156  return 0;
157}
158#endif
159
160/*
161 * Table of FAT file systems that will be mounted
162 * with the "fsmount" function.
163 * See cpukit/libmisc/fsmount for definition of fields
164 */
165fstab_t fs_table[] = {
166  {
167    "/dev/hda1","/mnt/hda1", "dosfs",
168    RTEMS_FILESYSTEM_READ_WRITE,
169    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
170    0
171  },
172  {
173    "/dev/hda2","/mnt/hda2", "dosfs",
174    RTEMS_FILESYSTEM_READ_WRITE,
175    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
176    0
177  },
178  {
179    "/dev/hda3","/mnt/hda3", "dosfs",
180    RTEMS_FILESYSTEM_READ_WRITE,
181    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
182    0
183  },
184  {
185    "/dev/hda4","/mnt/hda4", "dosfs",
186    RTEMS_FILESYSTEM_READ_WRITE,
187    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
188    0
189  },
190  {
191    "/dev/hdc1","/mnt/hdc1", "dosfs",
192    RTEMS_FILESYSTEM_READ_WRITE,
193    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
194    0
195  },
196  {
197    "/dev/hdc2","/mnt/hdc2", "dosfs",
198    RTEMS_FILESYSTEM_READ_WRITE,
199    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
200    0
201  },
202  {
203    "/dev/hdc3","/mnt/hdc3", "dosfs",
204    RTEMS_FILESYSTEM_READ_WRITE,
205    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
206    0
207  },
208  {
209    "/dev/hdc4","/mnt/hdc4", "dosfs",
210    RTEMS_FILESYSTEM_READ_WRITE,
211    FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
212    0
213  }
214};
215
216#define MIN(a,b) (((a) > (b)) ? (b) : (a))
217
218#define USE_SHELL
219
220#ifdef USE_SHELL
221
222static int
223shell_nvdisk_trace (int argc, char* argv[])
224{
225  const char* driver;
226  int         level;
227
228  if (argc != 3)
229  {
230    printf ("error: invalid number of options\n");
231    return 1;
232  }
233
234  driver = argv[1];
235  level  = strtoul (argv[2], 0, 0);
236 
237  int fd = open (driver, O_WRONLY, 0);
238  if (fd < 0)
239  {
240    printf ("error: driver open failed: %s\n", strerror (errno));
241    return 1;
242  }
243 
244  if (ioctl (fd, RTEMS_NVDISK_IOCTL_INFO_LEVEL, level) < 0)
245  {
246    printf ("error: driver set level failed: %s\n", strerror (errno));
247    return 1;
248  }
249 
250  close (fd);
251 
252  return 0;
253}
254
255static int
256shell_nvdisk_erase (int argc, char* argv[])
257{
258  const char* driver = NULL;
259  int         arg;
260  int         fd;
261 
262  for (arg = 1; arg < argc; arg++)
263  {
264    if (argv[arg][0] == '-')
265    {
266      printf ("error: invalid option: %s\n", argv[arg]);
267      return 1;
268    }
269    else
270    {
271      if (!driver)
272        driver = argv[arg];
273      else
274      {
275        printf ("error: only one driver name allowed: %s\n", argv[arg]);
276        return 1;
277      }
278    }
279  }
280 
281  printf ("erase nv disk: %s\n", driver);
282 
283  fd = open (driver, O_WRONLY, 0);
284  if (fd < 0)
285  {
286    printf ("error: nvdisk driver open failed: %s\n", strerror (errno));
287    return 1;
288  }
289 
290  if (ioctl (fd, RTEMS_NVDISK_IOCTL_ERASE_DISK) < 0)
291  {
292    printf ("error: nvdisk driver erase failed: %s\n", strerror (errno));
293    return 1;
294  }
295 
296  close (fd);
297 
298  printf ("nvdisk erased successful\n");
299
300  return 0;
301}
302
303static int
304shell_bdbuf_trace (int argc, char* argv[])
305{
306#if RTEMS_BDBUF_TRACE
307  extern bool rtems_bdbuf_tracer;
308  rtems_bdbuf_tracer = !rtems_bdbuf_tracer;
309  printf ("bdbuf trace: %d\n", rtems_bdbuf_tracer);
310#else
311  printf ("bdbuf trace disabled. Rebuild with enabled.\n");
312#endif
313  return 0;
314}
315
316static int
317disk_test_set_block_size (rtems_disk_device *dd, size_t size)
318{
319  return dd->ioctl (dd, RTEMS_BLKIO_SETBLKSIZE, &size);
320}
321
322static int
323disk_test_write_blocks (dev_t dev, int start, int count, size_t size)
324{
325  int                 block;
326  uint32_t*           ip;
327  uint32_t            value = 0;
328  int                 i;
329  rtems_bdbuf_buffer* bd;
330  rtems_status_code   sc;
331  int                 rv = 0;
332  rtems_disk_device* dd;
333 
334  dd = rtems_disk_obtain (dev);
335  if (!dd)
336  {
337    printf ("error: cannot obtain disk\n");
338    rv = 1;
339  }
340 
341  if (rv == 0 && disk_test_set_block_size (dd, size) < 0)
342  {
343    printf ("error: set block size failed: %s\n", strerror (errno));
344    rv = 1;
345  }
346
347  for (block = start; rv == 0 && block < (start + count); block++)
348  {
349    sc = rtems_bdbuf_read (dd, block, &bd);
350    if (sc == RTEMS_SUCCESSFUL)
351    {
352      ip = (uint32_t*) bd->buffer;
353      for (i = 0; i < (size / sizeof (uint32_t)); i++, ip++, value++)
354        *ip = (size << 16) | value;
355
356      sc = rtems_bdbuf_release_modified (bd);
357      if (sc != RTEMS_SUCCESSFUL)
358      {
359        printf ("error: release block %d bd failed: %s\n",
360                block, rtems_status_text (sc));
361        rv = 1;
362      }
363    }
364    else
365    {
366      printf ("error: get block %d bd failed: %s\n",
367              block, rtems_status_text (sc));
368      rv = 1;
369    }
370  }
371
372  rtems_disk_release (dd);
373
374  return rv;
375}
376
377static int
378disk_test_block_sizes (int argc, char *argv[])
379{
380  struct stat st;
381  char*       name;
382  int         start;
383  int         count;
384  int         size;
385 
386  if (argc != (4 + 1))
387  {
388    printf ("error: need to supply a device path, start, block and size\n");
389    return 1;
390  }
391
392  name = argv[1];
393 
394  if (stat (name, &st) < 0)
395  {
396    printf ("error: stat '%s' failed: %s\n", name, strerror (errno));
397    return 1;
398  }
399
400  start = strtoul (argv[2], 0, 0);
401  count = strtoul (argv[3], 0, 0);
402  size  = strtoul (argv[4], 0, 0);
403 
404  return disk_test_write_blocks (st.st_rdev, start, count, size);
405}
406
407static size_t
408parse_size_arg (const char* arg)
409{
410  size_t size;
411  size_t scalar = 1;
412 
413  size = strtoul (arg, 0, 0);
414  switch (arg[strlen (arg) - 1])
415  {
416    case 'M':
417      scalar = (size_t) 1000 * 1024;
418      break;
419    case 'm':
420      scalar = 1000000;
421      break;
422    case 'K':
423      scalar = 1024;
424      break;
425    case 'k':
426      scalar = 1000;
427      break;
428    default:
429      printf ("error: invalid scalar (M/m/K/k): %c\n", arg[strlen (arg) - 1]);
430      return 0;
431  }
432  return size * scalar;
433 }
434
435static int
436create_ramdisk (int argc, char *argv[])
437{
438  rtems_device_major_number major;
439  rtems_status_code         sc;
440  int                       arg;
441  size_t                    size = 0;
442  size_t                    block_size = 0;
443
444  for (arg = 0; arg < argc; ++arg)
445  {
446    if (argv[arg][0] == '-')
447    {
448      switch (argv[arg][0])
449      {
450        case 's':
451          ++arg;
452          if (arg == argc)
453          {
454            printf ("error: -s needs a size\n");
455            return 1;
456          }
457          size = parse_size_arg (argv[arg]);
458          if (size == 0)
459            return 1;
460          break;
461        case 'b':
462          ++arg;
463          if (arg == argc)
464          {
465            printf ("error: -b needs a size\n");
466            return 1;
467          }
468          block_size = parse_size_arg (argv[arg]);
469          if (size == 0)
470            return 1;
471          break;
472        default:
473          printf ("error: invalid option: %s\n", argv[arg]);
474          return 1;
475      }
476    }
477  }
478
479  if (block_size)
480    rtems_ramdisk_configuration[0].block_size = block_size;
481  if (size)
482    rtems_ramdisk_configuration[0].block_num =
483      size / rtems_ramdisk_configuration[0].block_size;
484   
485  /*
486   * Register the RAM Disk driver.
487   */
488  printf ("Register RAM Disk Driver [blocks=%" PRIu32 \
489          " block-size=%" PRIu32"]:",
490          rtems_ramdisk_configuration[0].block_num,
491          rtems_ramdisk_configuration[0].block_size);
492 
493  sc = rtems_io_register_driver (RTEMS_DRIVER_AUTO_MAJOR,
494                                 &rtems_ramdisk_io_ops,
495                                 &major);
496  if (sc != RTEMS_SUCCESSFUL)
497  {
498    printf ("error: ramdisk driver not initialised: %s\n",
499            rtems_status_text (sc));
500    return 1;
501  }
502 
503  printf ("successful\n");
504
505  return 0;
506}
507
508static int
509create_nvdisk (int argc, char *argv[])
510{
511  rtems_device_major_number major;
512  rtems_status_code         sc;
513  int                       arg;
514  size_t                    size = 0;
515#if ADD_WHEN_NVDISK_HAS_CHANGED
516  size_t                    block_size = 0;
517#endif
518 
519  for (arg = 0; arg < argc; ++arg)
520  {
521    if (argv[arg][0] == '-')
522    {
523      switch (argv[arg][0])
524      {
525        case 's':
526          ++arg;
527          if (arg == argc)
528          {
529            printf ("error: -s needs a size\n");
530            return 1;
531          }
532          size = parse_size_arg (argv[arg]);
533          if (size == 0)
534            return 1;
535          break;
536#if ADD_WHEN_NVDISK_HAS_CHANGED
537        case 'b':
538          ++arg;
539          if (arg == argc)
540          {
541            printf ("error: -b needs a size\n");
542            return 1;
543          }
544          block_size = parse_size_arg (argv[arg]);
545          if (size == 0)
546            return 1;
547          break;
548#endif
549        default:
550          printf ("error: invalid option: %s\n", argv[arg]);
551          return 1;
552      }
553    }
554  }
555
556#if ADD_WHEN_NVDISK_HAS_CHANGED
557  if (block_size)
558    rtems_nvdisk_configuration[0].block_size = block_size;
559#endif
560  if (size)
561    rtems_nv_heap_device_descriptor[0].size = size;
562   
563  /*
564   * For our test we do not have any static RAM or EEPROM devices so
565   * we allocate the memory from the heap.
566   */
567  rtems_nv_heap_device_descriptor[0].base =
568    malloc (rtems_nv_heap_device_descriptor[0].size);
569
570  if (!rtems_nv_heap_device_descriptor[0].base)
571  {
572    printf ("error: no memory for NV disk\n");
573    return 1;
574  }
575 
576  /*
577   * Register the RAM Disk driver.
578   */
579  printf ("Register NV Disk Driver [size=%" PRIu32 \
580          " block-size=%" PRIu32"]:",
581          rtems_nv_heap_device_descriptor[0].size,
582          rtems_nvdisk_configuration[0].block_size);
583 
584  sc = rtems_io_register_driver (RTEMS_DRIVER_AUTO_MAJOR,
585                                 &rtems_nvdisk_io_ops,
586                                 &major);
587  if (sc != RTEMS_SUCCESSFUL)
588  {
589    printf ("error: nvdisk driver not initialised: %s\n",
590            rtems_status_text (sc));
591    return 1;
592  }
593 
594  printf ("successful\n");
595
596  return 0;
597}
598
599static void writeFile(
600  const char *name,
601  mode_t      mode,
602  const char *contents
603)
604{
605  int sc;
606  sc = setuid(0);
607  if ( sc ) {
608    printf( "setuid failed: %s: %s\n", name, strerror(errno) );
609  }
610
611  rtems_shell_write_file( name, contents );
612
613  sc = chmod ( name, mode );
614  if ( sc ) {
615    printf( "chmod %s: %s\n", name, strerror(errno) );
616  }
617}
618
619#define writeScript( _name, _contents ) \
620        writeFile( _name, 0777, _contents )
621
622static void fileio_start_shell(void)
623{
624  int sc;
625
626  sc = mkdir("/scripts", 0777);
627  if ( sc ) {
628    printf( "mkdir /scripts: %s:\n", strerror(errno) );
629  }
630
631  sc = mkdir("/etc", 0777);
632  if ( sc ) {
633    printf( "mkdir /etc: %s:\n", strerror(errno) );
634  }
635
636  printf(
637    "Creating /etc/passwd and group with three useable accounts\n"
638    "root/pwd , test/pwd, rtems/NO PASSWORD"
639  );
640
641  writeFile(
642    "/etc/passwd",
643    0644,
644    "root:7QR4o148UPtb.:0:0:root::/:/bin/sh\n"
645    "rtems:*:1:1:RTEMS Application::/:/bin/sh\n"
646    "test:8Yy.AaxynxbLI:2:2:test account::/:/bin/sh\n"
647    "tty:!:3:3:tty owner::/:/bin/false\n"
648  );
649  writeFile(
650    "/etc/group",
651    0644,
652    "root:x:0:root\n"
653    "rtems:x:1:rtems\n"
654    "test:x:2:test\n"
655    "tty:x:3:tty\n"
656  );
657
658  writeScript(
659    "/scripts/js",
660    "#! joel\n"
661    "\n"
662    "date\n"
663    "echo Script successfully ran\n"
664    "date\n"
665    "stackuse\n"
666  );
667
668  writeScript(
669    "/scripts/j1",
670    "#! joel -s 20480 -t JESS\n"
671    "stackuse\n"
672  );
673
674  rtems_shell_write_file(
675    "/scripts/j2",
676    "echo j2 TEST FILE\n"
677    "echo j2   SHOULD BE non-executable AND\n"
678    "echo j2   DOES NOT have the magic first line\n"
679  );
680
681  rtems_shell_add_cmd ("mkrd", "files",
682                       "Create a RAM disk driver", create_ramdisk);
683  rtems_shell_add_cmd ("mknvd", "files",
684                       "Create a NV disk driver", create_nvdisk);
685  rtems_shell_add_cmd ("nverase", "misc",
686                       "nverase driver", shell_nvdisk_erase);
687  rtems_shell_add_cmd ("nvtrace", "misc",
688                       "nvtrace driver level", shell_nvdisk_trace);
689  rtems_shell_add_cmd ("bdbuftrace", "files",
690                       "bdbuf trace toggle", shell_bdbuf_trace);
691  rtems_shell_add_cmd ("td", "files",
692                       "Test disk", disk_test_block_sizes);
693#if RTEMS_RFS_TRACE
694  rtems_shell_add_cmd ("rfs", "files",
695                       "RFS trace",
696                       rtems_rfs_trace_shell_command);
697#endif
698#if RTEMS_RFS_RTEMS_TRACE
699  rtems_shell_add_cmd ("rrfs", "files",
700                       "RTEMS RFS trace",
701                       rtems_rfs_rtems_trace_shell_command);
702#endif
703
704  printf("\n =========================\n");
705  printf(" starting shell\n");
706  printf(" =========================\n");
707  rtems_shell_init(
708    "SHLL",                          /* task_name */
709    RTEMS_MINIMUM_STACK_SIZE * 4,    /* task_stacksize */
710    100,                             /* task_priority */
711    "/dev/foobar",                   /* devname */
712    /* device is currently ignored by the shell if it is not a pty */
713    false,                           /* forever */
714    true,                            /* wait */
715    rtems_shell_login_check          /* login */
716  );
717}
718#endif /* USE_SHELL */
719
720static void fileio_print_free_heap(void)
721{
722  printf("--- unused dynamic memory: %lu bytes ---\n",
723         (unsigned long) malloc_free_space());
724}
725
726
727static void fileio_part_table_initialize(void)
728{
729  char devname[64];
730  rtems_status_code rc;
731
732  printf(" =========================\n");
733  printf(" Initialize partition table\n");
734  printf(" =========================\n");
735  fileio_print_free_heap();
736  printf(" Enter device to initialize ==>");
737  fflush(stdout);
738  fgets(devname,sizeof(devname)-1,stdin);
739  while (devname[strlen(devname)-1] == '\n') {
740    devname[strlen(devname)-1] = '\0';
741  }
742  /*
743   * call function
744   */
745  rc = rtems_bdpart_register_from_disk(devname);
746  printf("result = %d\n",rc);
747  fileio_print_free_heap();
748}
749
750static void fileio_fsmount(void)
751{
752  rtems_status_code rc;
753
754  printf(" =========================\n");
755  printf(" Process fsmount table\n");
756  printf(" =========================\n");
757  fileio_print_free_heap();
758  /*
759   * call function
760   */
761  rc = rtems_fsmount( fs_table,
762                      sizeof(fs_table)/sizeof(fs_table[0]),
763                      NULL);
764  printf("result = %d\n",rc);
765  fileio_print_free_heap();
766}
767
768static void fileio_list_file(void)
769{
770  char fname[1024];
771  char *buf_ptr = NULL;
772  ssize_t   flen = 0;
773  int fd = -1;
774  ssize_t n;
775  size_t buf_size = 100;
776
777  rtems_interval start_tick,curr_tick,ticks_per_sec;
778
779  printf(" =========================\n");
780  printf(" LIST FILE ...            \n");
781  printf(" =========================\n");
782  fileio_print_free_heap();
783  printf(" Enter filename to list ==>");
784  fflush(stdout);
785  fgets(fname,sizeof(fname)-1,stdin);
786  while (fname[strlen(fname)-1] == '\n') {
787    fname[strlen(fname)-1] = '\0';
788  }
789  /*
790   * allocate buffer of given size
791   */
792  if (buf_size > 0) {
793    buf_ptr = malloc(buf_size);
794  }
795
796  if (buf_ptr != NULL) {
797    printf("\n Trying to open file \"%s\" for read\n",fname);
798    fd = open(fname,O_RDONLY);
799    if (fd < 0) {
800      printf("*** file open failed, errno = %d(%s)\n",errno,strerror(errno));
801    }
802  }
803
804  if (fd >= 0) {
805    start_tick = rtems_clock_get_ticks_since_boot();
806    do {
807      n = read(fd,buf_ptr,buf_size);
808      if (n > 0) {
809        write(1,buf_ptr,(size_t) n);
810        flen += n;
811      }
812    } while (n > 0);
813
814    curr_tick = rtems_clock_get_ticks_since_boot();
815
816    printf("\n ******** End of file reached, flen = %zd\n",flen);
817    close(fd);
818
819    ticks_per_sec = rtems_clock_get_ticks_per_second();
820    printf("time elapsed for read:  %g seconds\n",
821           ((double)curr_tick-start_tick)/ticks_per_sec);
822  }
823  /*
824   * free buffer
825   */
826  if (buf_ptr != NULL) {
827    free(buf_ptr);
828  }
829  fileio_print_free_heap();
830}
831
832/*
833 * convert a size string (like 34K or 12M) to actual byte count
834 */
835static bool fileio_str2size(const char *str,uint32_t   *res_ptr)
836{
837  bool failed = false;
838  unsigned long size;
839  unsigned char suffix = ' ';
840
841  if (1 > sscanf(str,"%lu%c",&size,&suffix)) {
842    failed = true;
843  }
844  else if (toupper((int)suffix) == 'K') {
845    size *= 1024;
846  }
847  else if (toupper((int)suffix) == 'M') {
848    size *= 1024UL*1024UL;
849  }
850  else if (isalpha((int)suffix)) {
851    failed = true;
852  }
853
854  if (!failed) {
855    *res_ptr = size;
856  }
857  return failed;
858}
859
860static void fileio_write_file(void)
861{
862  char fname[1024];
863  char tmp_str[32];
864  uint32_t   file_size = 0;
865  uint32_t   buf_size  = 0;
866  size_t curr_pos,bytes_to_copy;
867  int fd = -1;
868  ssize_t n;
869  rtems_interval start_tick,curr_tick,ticks_per_sec;
870  char *bufptr = NULL;
871  bool failed = false;
872  static const char write_test_string[] =
873    "The quick brown fox jumps over the lazy dog\n";
874  static const char write_block_string[] =
875    "\n----- end of write buffer ------\n";
876
877  printf(" =========================\n");
878  printf(" WRITE FILE ...           \n");
879  printf(" =========================\n");
880  fileio_print_free_heap();
881  /*
882   * get number of ticks per second
883   */
884  ticks_per_sec = rtems_clock_get_ticks_per_second();
885
886  /*
887   * get path to file to write
888   */
889  if (!failed) {
890    printf("Enter path/filename ==>");
891    fflush(stdout);
892    fgets(fname,sizeof(fname)-1,stdin);
893    while (fname[strlen(fname)-1] == '\n') {
894      fname[strlen(fname)-1] = '\0';
895    }
896    if (0 == strlen(fname)) {
897      printf("*** no filename entered, aborted\n");
898      failed = true;
899    }
900  }
901  /*
902   * get total file size to write
903   */
904  if (!failed) {
905    printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
906           "Enter filesize to write ==>");
907    fflush(stdout);
908    fgets(tmp_str,sizeof(tmp_str)-1,stdin);
909    failed = fileio_str2size(tmp_str,&file_size);
910    if (failed) {
911      printf("*** illegal file size, aborted\n");
912    }
913  }
914  /*
915   * get block size to write
916   */
917  if (!failed) {
918    printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
919           "Enter block size to use for write calls ==>");
920    fflush(stdout);
921    fgets(tmp_str,sizeof(tmp_str)-1,stdin);
922    failed = fileio_str2size(tmp_str,&buf_size);
923    if (failed) {
924      printf("*** illegal block size, aborted\n");
925    }
926  }
927
928  /*
929   * allocate buffer
930   */
931  if (!failed) {
932    printf("... allocating %lu bytes of buffer for write data\n",
933           (unsigned long)buf_size);
934    bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
935    if (bufptr == NULL) {
936      printf("*** malloc failed, aborted\n");
937      failed = true;
938    }
939  }
940  /*
941   * fill buffer with test pattern
942   */
943  if (!failed) {
944    printf("... filling buffer with write data\n");
945    curr_pos = 0;
946    /*
947     * fill buffer with test string
948     */
949    while (curr_pos < buf_size) {
950      bytes_to_copy = MIN(buf_size-curr_pos,
951                          sizeof(write_test_string)-1);
952      memcpy(bufptr+curr_pos,write_test_string,bytes_to_copy);
953      curr_pos += bytes_to_copy;
954    }
955    /*
956     * put "end" mark at end of buffer
957     */
958    bytes_to_copy = sizeof(write_block_string)-1;
959    if (buf_size >= bytes_to_copy) {
960      memcpy(bufptr+buf_size-bytes_to_copy,
961             write_block_string,
962             bytes_to_copy);
963    }
964  }
965  /*
966   * create file
967   */
968  if (!failed) {
969    printf("... creating file \"%s\"\n",fname);
970    fd = open(fname,O_WRONLY | O_CREAT | O_TRUNC,S_IREAD|S_IWRITE);
971    if (fd < 0) {
972      printf("*** file create failed, errno = %d(%s)\n",errno,strerror(errno));
973      failed = true;
974    }
975  }
976  /*
977   * write file
978   */
979  if (!failed) {
980    printf("... writing to file\n");
981    start_tick = rtems_clock_get_ticks_since_boot();
982    curr_pos = 0;
983    do {
984      bytes_to_copy = buf_size;
985      do {
986        n = write(fd,
987          bufptr + (buf_size-bytes_to_copy),
988                  MIN(bytes_to_copy,file_size-curr_pos));
989        if (n > 0) {
990          bytes_to_copy -= (size_t) n;
991          curr_pos      += (size_t) n;
992        }
993      } while ((bytes_to_copy > 0)  && (n > 0));
994    } while ((file_size > curr_pos) && (n > 0));
995    curr_tick = rtems_clock_get_ticks_since_boot();
996    if (n < 0) {
997      failed = true;
998      printf("*** file write failed, "
999             "%lu bytes written, "
1000             "errno = %d(%s)\n",
1001             (unsigned long)curr_pos,errno,strerror(errno));
1002    }
1003    else {
1004      printf("time elapsed for write:  %g seconds\n",
1005             ((double)curr_tick-start_tick)/ticks_per_sec);
1006      printf("write data rate: %g KBytes/second\n",
1007             (((double)file_size) / 1024.0 /
1008              (((double)curr_tick-start_tick)/ticks_per_sec)));
1009    }
1010  }
1011  if (fd >= 0) {
1012    printf("... closing file\n");
1013    close(fd);
1014  }
1015  if (bufptr != NULL) {
1016    printf("... deallocating buffer\n");
1017    free(bufptr);
1018    bufptr = NULL;
1019  }
1020  printf("\n ******** End of file write\n");
1021  fileio_print_free_heap();
1022}
1023
1024static void fileio_read_file(void)
1025{
1026  char fname[1024];
1027  char tmp_str[32];
1028  uint32_t   buf_size  = 0;
1029  size_t curr_pos;
1030  int fd = -1;
1031  ssize_t n;
1032  rtems_interval start_tick,curr_tick,ticks_per_sec;
1033  char *bufptr = NULL;
1034  bool failed = false;
1035
1036  printf(" =========================\n");
1037  printf(" READ FILE ...            \n");
1038  printf(" =========================\n");
1039  fileio_print_free_heap();
1040  /*
1041   * get number of ticks per second
1042   */
1043  ticks_per_sec = rtems_clock_get_ticks_per_second();
1044
1045  /*
1046   * get path to file to read
1047   */
1048  if (!failed) {
1049    printf("Enter path/filename ==>");
1050    fflush(stdout);
1051    fgets(fname,sizeof(fname)-1,stdin);
1052    while (fname[strlen(fname)-1] == '\n') {
1053      fname[strlen(fname)-1] = '\0';
1054    }
1055    if (0 == strlen(fname)) {
1056      printf("*** no filename entered, aborted\n");
1057      failed = true;
1058    }
1059  }
1060  /*
1061   * get block size to read
1062   */
1063  if (!failed) {
1064    printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
1065           "Enter block size to use for read calls ==>");
1066    fflush(stdout);
1067    fgets(tmp_str,sizeof(tmp_str)-1,stdin);
1068    failed = fileio_str2size(tmp_str,&buf_size);
1069    if (failed) {
1070      printf("*** illegal block size, aborted\n");
1071    }
1072  }
1073
1074  /*
1075   * allocate buffer
1076   */
1077  if (!failed) {
1078    printf("... allocating %lu bytes of buffer for write data\n",
1079           (unsigned long)buf_size);
1080    bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
1081    if (bufptr == NULL) {
1082      printf("*** malloc failed, aborted\n");
1083      failed = true;
1084    }
1085  }
1086  /*
1087   * open file
1088   */
1089  if (!failed) {
1090    printf("... opening file \"%s\"\n",fname);
1091    fd = open(fname,O_RDONLY);
1092    if (fd < 0) {
1093      printf("*** file open failed, errno = %d(%s)\n",errno,strerror(errno));
1094      failed = true;
1095    }
1096  }
1097  /*
1098   * read file
1099   */
1100  if (!failed) {
1101    printf("... reading from file\n");
1102    start_tick = rtems_clock_get_ticks_since_boot();
1103    curr_pos = 0;
1104    do {
1105      n = read(fd,
1106               bufptr,
1107               buf_size);
1108      if (n > 0) {
1109        curr_pos      += (size_t) n;
1110      }
1111    } while (n > 0);
1112    curr_tick = rtems_clock_get_ticks_since_boot();
1113    if (n < 0) {
1114      failed = true;
1115      printf("*** file read failed, "
1116             "%lu bytes read, "
1117             "errno = %d(%s)\n",
1118             (unsigned long)curr_pos,errno,strerror(errno));
1119    }
1120    else {
1121      printf("%lu bytes read\n",
1122             (unsigned long)curr_pos);
1123      printf("time elapsed for read:  %g seconds\n",
1124             ((double)curr_tick-start_tick)/ticks_per_sec);
1125      printf("read data rate: %g KBytes/second\n",
1126             (((double)curr_pos) / 1024.0 /
1127              (((double)curr_tick-start_tick)/ticks_per_sec)));
1128    }
1129  }
1130  if (fd >= 0) {
1131    printf("... closing file\n");
1132    close(fd);
1133  }
1134  if (bufptr != NULL) {
1135    printf("... deallocating buffer\n");
1136    free(bufptr);
1137    bufptr = NULL;
1138  }
1139  printf("\n ******** End of file read\n");
1140  fileio_print_free_heap();
1141
1142}
1143
1144static void fileio_menu (void)
1145{
1146  char inbuf[10];
1147
1148  /*
1149   * Wait for characters from console terminal
1150   */
1151  for (;;) {
1152    printf(" =========================\n");
1153    printf(" RTEMS FILE I/O Test Menu \n");
1154    printf(" =========================\n");
1155    printf("   p -> part_table_initialize\n");
1156    printf("   f -> mount all disks in fs_table\n");
1157    printf("   l -> list  file\n");
1158    printf("   r -> read  file\n");
1159    printf("   w -> write file\n");
1160#ifdef USE_SHELL
1161    printf("   s -> start shell\n");
1162#endif
1163    printf("   Enter your selection ==>");
1164    fflush(stdout);
1165
1166    inbuf[0] = '\0';
1167    fgets(inbuf,sizeof(inbuf),stdin);
1168    switch (inbuf[0]) {
1169    case 'l':
1170      fileio_list_file ();
1171      break;
1172    case 'r':
1173      fileio_read_file ();
1174      break;
1175    case 'w':
1176      fileio_write_file ();
1177      break;
1178    case 'p':
1179      fileio_part_table_initialize ();
1180      break;
1181    case 'f':
1182      fileio_fsmount ();
1183      break;
1184#ifdef USE_SHELL
1185    case 's':
1186      fileio_start_shell ();
1187      break;
1188#endif
1189    default:
1190      printf("Selection `%c` not implemented\n",inbuf[0]);
1191      break;
1192    }
1193
1194  }
1195  exit (0);
1196}
1197
1198/*
1199 * RTEMS File Menu Task
1200 */
1201static rtems_task
1202fileio_task (rtems_task_argument ignored)
1203{
1204  fileio_menu();
1205}
1206
1207static void
1208notification (int fd, int seconds_remaining, void *arg)
1209{
1210  printf(
1211    "Press any key to start file I/O sample (%is remaining)\n",
1212    seconds_remaining
1213  );
1214}
1215
1216/*
1217 * RTEMS Startup Task
1218 */
1219rtems_task
1220Init (rtems_task_argument ignored)
1221{
1222  rtems_name Task_name;
1223  rtems_id   Task_id;
1224  rtems_status_code status;
1225
1226  TEST_BEGIN();
1227
1228  status = rtems_shell_wait_for_input(
1229    STDIN_FILENO,
1230    20,
1231    notification,
1232    NULL
1233  );
1234  if (status == RTEMS_SUCCESSFUL) {
1235    Task_name = rtems_build_name('F','M','N','U');
1236
1237    status = rtems_task_create(
1238      Task_name, 1, RTEMS_MINIMUM_STACK_SIZE * 2,
1239      RTEMS_DEFAULT_MODES ,
1240      RTEMS_FLOATING_POINT | RTEMS_DEFAULT_ATTRIBUTES, &Task_id
1241    );
1242    directive_failed( status, "create" );
1243
1244    status = rtems_task_start( Task_id, fileio_task, 1 );
1245    directive_failed( status, "start" );
1246
1247    status = rtems_task_delete( RTEMS_SELF );
1248    directive_failed( status, "delete" );
1249  } else {
1250    TEST_END();
1251
1252    rtems_test_exit( 0 );
1253  }
1254}
1255
1256#if defined(USE_SHELL)
1257/*
1258 *  RTEMS Shell Configuration -- Add a command and an alias for it
1259 */
1260
1261static int main_usercmd(int argc, char **argv)
1262{
1263  int i;
1264  printf( "UserCommand: argc=%d\n", argc );
1265  for (i=0 ; i<argc ; i++ )
1266    printf( "argv[%d]= %s\n", i, argv[i] );
1267  return 0;
1268}
1269
1270static rtems_shell_cmd_t Shell_USERCMD_Command = {
1271  "usercmd",                                       /* name */
1272  "usercmd n1 [n2 [n3...]]     # echo arguments",  /* usage */
1273  "user",                                          /* topic */
1274  main_usercmd,                                    /* command */
1275  NULL,                                            /* alias */
1276  NULL                                             /* next */
1277};
1278
1279static rtems_shell_alias_t Shell_USERECHO_Alias = {
1280  "usercmd",                 /* command */
1281  "userecho"                 /* alias */
1282};
1283
1284
1285#define CONFIGURE_SHELL_USER_COMMANDS &Shell_USERCMD_Command
1286#define CONFIGURE_SHELL_USER_ALIASES &Shell_USERECHO_Alias
1287#define CONFIGURE_SHELL_COMMANDS_INIT
1288#define CONFIGURE_SHELL_COMMANDS_ALL
1289#define CONFIGURE_SHELL_MOUNT_MSDOS
1290#define CONFIGURE_SHELL_MOUNT_RFS
1291#define CONFIGURE_SHELL_DEBUGRFS
1292
1293#include <rtems/shellconfig.h>
1294#endif
1295
1296#else
1297/*
1298 * RTEMS Startup Task
1299 */
1300rtems_task
1301Init (rtems_task_argument ignored)
1302{
1303  puts( "\n\n*** FILE I/O SAMPLE AND TEST ***" );
1304  puts( "\n\n*** NOT ENOUGH MEMORY TO BUILD AND RUN ***" );
1305}
1306#endif
Note: See TracBrowser for help on using the repository browser.