Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:42

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  COPYRIGHT (c) 1989-2012.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #define CONFIGURE_INIT
0034 #include "system.h"
0035 #include <sys/param.h>
0036 #include <crypt.h>
0037 #include <stdio.h>
0038 #include <string.h>
0039 #include <unistd.h>
0040 #include <stdlib.h>
0041 #include <errno.h>
0042 #include <rtems.h>
0043 #include <fcntl.h>
0044 #include <inttypes.h>
0045 #include <rtems/error.h>
0046 #include <rtems/dosfs.h>
0047 #include <ctype.h>
0048 #include <rtems/bdpart.h>
0049 #include <rtems/libcsupport.h>
0050 #include <rtems/fsmount.h>
0051 #include <rtems/ramdisk.h>
0052 #include <rtems/nvdisk.h>
0053 #include <rtems/nvdisk-sram.h>
0054 #include <rtems/shell.h>
0055 
0056 const char rtems_test_name[] = "FILE I/O";
0057 
0058 #if FILEIO_BUILD
0059 
0060 /**
0061  * Let the IO system allocation the next available major number.
0062  */
0063 #define RTEMS_DRIVER_AUTO_MAJOR (0)
0064 
0065 /**
0066  * The NV Device descriptor. For this test it is just DRAM.
0067  */
0068 rtems_nvdisk_device_desc rtems_nv_heap_device_descriptor[] =
0069 {
0070   {
0071     flags:  0,
0072     base:   0,
0073     size:   (size_t) 1024 * 1024,
0074     nv_ops: &rtems_nvdisk_sram_handlers
0075   }
0076 };
0077 
0078 /**
0079  * The NV Disk configuration.
0080  */
0081 const rtems_nvdisk_config rtems_nvdisk_configuration[] =
0082 {
0083   {
0084     block_size:         512,
0085     device_count:       1,
0086     devices:            &rtems_nv_heap_device_descriptor[0],
0087     flags:              0,
0088     info_level:         0
0089   }
0090 };
0091 
0092 /**
0093  * The number of NV Disk configurations.
0094  */
0095 uint32_t rtems_nvdisk_configuration_size = 1;
0096 
0097 /*
0098  * Table of FAT file systems that will be mounted
0099  * with the "fsmount" function.
0100  * See cpukit/libmisc/fsmount for definition of fields
0101  */
0102 fstab_t fs_table[] = {
0103   {
0104     "/dev/hda1","/mnt/hda1", "dosfs",
0105     RTEMS_FILESYSTEM_READ_WRITE,
0106     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0107     0
0108   },
0109   {
0110     "/dev/hda2","/mnt/hda2", "dosfs",
0111     RTEMS_FILESYSTEM_READ_WRITE,
0112     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0113     0
0114   },
0115   {
0116     "/dev/hda3","/mnt/hda3", "dosfs",
0117     RTEMS_FILESYSTEM_READ_WRITE,
0118     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0119     0
0120   },
0121   {
0122     "/dev/hda4","/mnt/hda4", "dosfs",
0123     RTEMS_FILESYSTEM_READ_WRITE,
0124     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0125     0
0126   },
0127   {
0128     "/dev/hdc1","/mnt/hdc1", "dosfs",
0129     RTEMS_FILESYSTEM_READ_WRITE,
0130     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0131     0
0132   },
0133   {
0134     "/dev/hdc2","/mnt/hdc2", "dosfs",
0135     RTEMS_FILESYSTEM_READ_WRITE,
0136     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0137     0
0138   },
0139   {
0140     "/dev/hdc3","/mnt/hdc3", "dosfs",
0141     RTEMS_FILESYSTEM_READ_WRITE,
0142     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0143     0
0144   },
0145   {
0146     "/dev/hdc4","/mnt/hdc4", "dosfs",
0147     RTEMS_FILESYSTEM_READ_WRITE,
0148     FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED,
0149     0
0150   }
0151 };
0152 
0153 #define USE_SHELL
0154 
0155 #ifdef USE_SHELL
0156 
0157 static int
0158 shell_nvdisk_trace (int argc, char* argv[])
0159 {
0160   const char* driver;
0161   int         level;
0162 
0163   if (argc != 3)
0164   {
0165     printf ("error: invalid number of options\n");
0166     return 1;
0167   }
0168 
0169   driver = argv[1];
0170   level  = strtoul (argv[2], 0, 0);
0171   
0172   int fd = open (driver, O_WRONLY, 0);
0173   if (fd < 0)
0174   {
0175     printf ("error: driver open failed: %s\n", strerror (errno));
0176     return 1;
0177   }
0178   
0179   if (ioctl (fd, RTEMS_NVDISK_IOCTL_INFO_LEVEL, level) < 0)
0180   {
0181     printf ("error: driver set level failed: %s\n", strerror (errno));
0182     return 1;
0183   }
0184   
0185   close (fd);
0186   
0187   return 0;
0188 }
0189 
0190 static int
0191 shell_nvdisk_erase (int argc, char* argv[])
0192 {
0193   const char* driver = NULL;
0194   int         arg;
0195   int         fd;
0196   
0197   for (arg = 1; arg < argc; arg++)
0198   {
0199     if (argv[arg][0] == '-')
0200     {
0201       printf ("error: invalid option: %s\n", argv[arg]);
0202       return 1;
0203     }
0204     else
0205     {
0206       if (!driver)
0207         driver = argv[arg];
0208       else
0209       {
0210         printf ("error: only one driver name allowed: %s\n", argv[arg]);
0211         return 1;
0212       }
0213     }
0214   }
0215   
0216   printf ("erase nv disk: %s\n", driver);
0217   
0218   fd = open (driver, O_WRONLY, 0);
0219   if (fd < 0)
0220   {
0221     printf ("error: nvdisk driver open failed: %s\n", strerror (errno));
0222     return 1;
0223   }
0224   
0225   if (ioctl (fd, RTEMS_NVDISK_IOCTL_ERASE_DISK) < 0)
0226   {
0227     printf ("error: nvdisk driver erase failed: %s\n", strerror (errno));
0228     return 1;
0229   }
0230   
0231   close (fd);
0232   
0233   printf ("nvdisk erased successful\n");
0234 
0235   return 0;
0236 }
0237 
0238 static int
0239 shell_bdbuf_trace (int argc, char* argv[])
0240 {
0241 #if RTEMS_BDBUF_TRACE
0242   extern bool rtems_bdbuf_tracer;
0243   rtems_bdbuf_tracer = !rtems_bdbuf_tracer;
0244   printf ("bdbuf trace: %d\n", rtems_bdbuf_tracer);
0245 #else
0246   printf ("bdbuf trace disabled. Rebuild with enabled.\n");
0247 #endif
0248   return 0;
0249 }
0250 
0251 static int
0252 disk_test_set_block_size (rtems_disk_device *dd, size_t size)
0253 {
0254   return dd->ioctl (dd, RTEMS_BLKIO_SETBLKSIZE, &size);
0255 }
0256 
0257 static int
0258 disk_test_write_blocks (const char *name, int start, int count, size_t size)
0259 {
0260   int                 block;
0261   uint32_t*           ip;
0262   uint32_t            value = 0;
0263   int                 i;
0264   rtems_bdbuf_buffer* bd;
0265   rtems_status_code   sc;
0266   int                 rv = 0;
0267   rtems_disk_device*  dd;
0268   int                 fd;
0269 
0270   fd = open(name, O_RDWR);
0271   if (fd < 0) {
0272     printf ("error: cannot open disk\n");
0273     rv = 1;
0274   }
0275 
0276   if (rv == 0 && rtems_disk_fd_get_disk_device(fd, &dd) != 0)
0277   {
0278     printf ("error: cannot obtain disk\n");
0279     rv = 1;
0280   }
0281 
0282   if (fd >= 0 && close (fd) != 0)
0283   {
0284     printf ("error: close disk failed\n");
0285     rv = 1;
0286   }
0287 
0288   if (rv == 0 && disk_test_set_block_size (dd, size) < 0)
0289   {
0290     printf ("error: set block size failed: %s\n", strerror (errno));
0291     rv = 1;
0292   }
0293 
0294   for (block = start; rv == 0 && block < (start + count); block++)
0295   {
0296     sc = rtems_bdbuf_read (dd, block, &bd);
0297     if (sc == RTEMS_SUCCESSFUL)
0298     {
0299       ip = (uint32_t*) bd->buffer;
0300       for (i = 0; i < (size / sizeof (uint32_t)); i++, ip++, value++)
0301         *ip = (size << 16) | value;
0302 
0303       sc = rtems_bdbuf_release_modified (bd);
0304       if (sc != RTEMS_SUCCESSFUL)
0305       {
0306         printf ("error: release block %d bd failed: %s\n",
0307                 block, rtems_status_text (sc));
0308         rv = 1;
0309       }
0310     }
0311     else
0312     {
0313       printf ("error: get block %d bd failed: %s\n",
0314               block, rtems_status_text (sc));
0315       rv = 1;
0316     }
0317   }
0318 
0319   return rv;
0320 }
0321 
0322 static int
0323 disk_test_block_sizes (int argc, char *argv[])
0324 {
0325   char* name;
0326   int   start;
0327   int   count;
0328   int   size;
0329 
0330   if (argc != (4 + 1))
0331   {
0332     printf ("error: need to supply a device path, start, block and size\n");
0333     return 1;
0334   }
0335 
0336   name = argv[1];
0337 
0338   start = strtoul (argv[2], 0, 0);
0339   count = strtoul (argv[3], 0, 0);
0340   size  = strtoul (argv[4], 0, 0);
0341 
0342   return disk_test_write_blocks (name, start, count, size);
0343 }
0344 
0345 static uint32_t
0346 parse_size_arg (const char* arg)
0347 {
0348   uint32_t size;
0349   uint32_t scalar = 1;
0350 
0351   size = strtoul (arg, 0, 0);
0352   switch (arg[strlen (arg) - 1])
0353   {
0354     case 'b':
0355       scalar = 1;
0356       break;
0357     case 'M':
0358       scalar = 1024000;
0359       break;
0360     case 'm':
0361       scalar = 1000000;
0362       break;
0363     case 'K':
0364       scalar = 1024;
0365       break;
0366     case 'k':
0367       scalar = 1000;
0368       break;
0369     default:
0370       printf ("error: invalid scalar (b,M/m/K/k): %c\n", arg[strlen (arg) - 1]);
0371       return 0;
0372   }
0373   return size * scalar;
0374 }
0375 
0376 static int
0377 create_ramdisk (int argc, char *argv[])
0378 {
0379   rtems_status_code         sc;
0380   int                       arg;
0381   uint32_t                  size = 524288;
0382   uint32_t                  block_size = 512;
0383   uint32_t                  block_count;
0384 
0385   for (arg = 0; arg < argc; ++arg)
0386   {
0387     if (argv[arg][0] == '-')
0388     {
0389       switch (argv[arg][1])
0390       {
0391         case 's':
0392           ++arg;
0393           if (arg == argc)
0394           {
0395             printf ("error: -s needs a size\n");
0396             return 1;
0397           }
0398           size = parse_size_arg (argv[arg]);
0399           if (size == 0)
0400             return 1;
0401           break;
0402         case 'b':
0403           ++arg;
0404           if (arg == argc)
0405           {
0406             printf ("error: -b needs a size\n");
0407             return 1;
0408           }
0409           block_size = parse_size_arg (argv[arg]);
0410           if (size == 0)
0411             return 1;
0412           break;
0413         default:
0414           printf ("error: invalid option: %s\n", argv[arg]);
0415           return 1;
0416       }
0417     }
0418   }
0419 
0420   block_count = size / block_size;
0421 
0422   /*
0423    * Register the RAM Disk driver.
0424    */
0425   printf ("Register RAM Disk Driver [blocks=%" PRIu32 \
0426           " block-size=%" PRIu32 "]:",
0427           block_count,
0428           block_size);
0429 
0430   sc = ramdisk_register(block_size, block_count, false, "/dev/rda");
0431   if (sc != RTEMS_SUCCESSFUL)
0432   {
0433     printf ("error: ramdisk driver not initialised: %s\n",
0434             rtems_status_text (sc));
0435     return 1;
0436   }
0437 
0438   printf ("successful\n");
0439 
0440   return 0;
0441 }
0442 
0443 static int
0444 create_nvdisk (int argc, char *argv[])
0445 {
0446   rtems_status_code         sc;
0447   int                       arg;
0448   uint32_t                  size = 0;
0449 #if ADD_WHEN_NVDISK_HAS_CHANGED
0450   uint32_t                  block_size = 0;
0451 #endif
0452   
0453   for (arg = 0; arg < argc; ++arg)
0454   {
0455     if (argv[arg][0] == '-')
0456     {
0457       switch (argv[arg][1])
0458       {
0459         case 's':
0460           ++arg;
0461           if (arg == argc)
0462           {
0463             printf ("error: -s needs a size\n");
0464             return 1;
0465           }
0466           size = parse_size_arg (argv[arg]);
0467           if (size == 0)
0468             return 1;
0469           break;
0470 #if ADD_WHEN_NVDISK_HAS_CHANGED
0471         case 'b':
0472           ++arg;
0473           if (arg == argc)
0474           {
0475             printf ("error: -b needs a size\n");
0476             return 1;
0477           }
0478           block_size = parse_size_arg (argv[arg]);
0479           if (size == 0)
0480             return 1;
0481           break;
0482 #endif
0483         default:
0484           printf ("error: invalid option: %s\n", argv[arg]);
0485           return 1;
0486       }
0487     }
0488   }
0489 
0490 #if ADD_WHEN_NVDISK_HAS_CHANGED
0491   if (block_size)
0492     rtems_nvdisk_configuration[0].block_size = block_size;
0493 #endif
0494   if (size)
0495     rtems_nv_heap_device_descriptor[0].size = size;
0496     
0497   /*
0498    * For our test we do not have any static RAM or EEPROM devices so
0499    * we allocate the memory from the heap.
0500    */
0501   rtems_nv_heap_device_descriptor[0].base =
0502     malloc (rtems_nv_heap_device_descriptor[0].size);
0503 
0504   if (!rtems_nv_heap_device_descriptor[0].base)
0505   {
0506     printf ("error: no memory for NV disk\n");
0507     return 1;
0508   }
0509   
0510   /*
0511    * Register the RAM Disk driver.
0512    */
0513   printf ("Register NV Disk Driver [size=%" PRIu32 \
0514           " block-size=%" PRIu32"]:",
0515           rtems_nv_heap_device_descriptor[0].size,
0516           rtems_nvdisk_configuration[0].block_size);
0517 
0518   sc = rtems_nvdisk_initialize (0, 0, NULL);
0519   if (sc != RTEMS_SUCCESSFUL)
0520   {
0521     printf ("error: nvdisk driver not initialised: %s\n",
0522             rtems_status_text (sc));
0523     return 1;
0524   }
0525   
0526   printf ("successful\n");
0527 
0528   return 0;
0529 }
0530 
0531 static void writeFile(
0532   const char *name,
0533   mode_t      mode,
0534   const char *contents
0535 )
0536 {
0537   int sc;
0538   sc = setuid(0);
0539   if ( sc ) {
0540     printf( "setuid failed: %s: %s\n", name, strerror(errno) );
0541   }
0542 
0543   rtems_shell_write_file( name, contents );
0544 
0545   sc = chmod ( name, mode );
0546   if ( sc ) {
0547     printf( "chmod %s: %s\n", name, strerror(errno) );
0548   }
0549 }
0550 
0551 #define writeScript( _name, _contents ) \
0552         writeFile( _name, 0777, _contents )
0553 
0554 static void fileio_start_shell(void)
0555 {
0556   int sc;
0557 
0558   sc = mkdir("/scripts", 0777);
0559   if ( sc ) {
0560     printf( "mkdir /scripts: %s:\n", strerror(errno) );
0561   }
0562 
0563   sc = mkdir("/etc", 0777);
0564   if ( sc ) {
0565     printf( "mkdir /etc: %s:\n", strerror(errno) );
0566   }
0567 
0568   sc = mkdir("/chroot", 0777);
0569   if ( sc ) {
0570     printf( "mkdir /chroot: %s:\n", strerror(errno) );
0571   }
0572 
0573   printf(
0574     "Creating /etc/passwd and group with four useable accounts:\n"
0575     "  root/pwd\n"
0576     "  test/pwd\n"
0577     "  rtems/NO PASSWORD\n"
0578     "  chroot/NO PASSWORD\n"
0579     "Only the root user has access to all available commands.\n"
0580   );
0581 
0582   writeFile(
0583     "/etc/passwd",
0584     0644,
0585     "root:$6$$FuPOhnllx6lhW2qqlnmWvZQLJ8Thr/09I7ESTdb9VbnTOn5.65"
0586       "/Vh2Mqa6FoKXwT0nHS/O7F0KfrDc6Svb/sH.:0:0:root::/:/bin/sh\n"
0587     "rtems::1:1:RTEMS Application::/:/bin/sh\n"
0588     "test:$1$$oPu1Xt2Pw0ngIc7LyDHqu1:2:2:test account::/:/bin/sh\n"
0589     "tty:*:3:3:tty owner::/:/bin/false\n"
0590     "chroot::4:2:chroot account::/chroot:/bin/sh\n"
0591   );
0592   writeFile(
0593     "/etc/group",
0594     0644,
0595     "root:x:0:root\n"
0596     "rtems:x:1:rtems\n"
0597     "test:x:2:test\n"
0598     "tty:x:3:tty\n"
0599   );
0600 
0601   writeScript(
0602     "/scripts/js",
0603     "#! joel\n"
0604     "\n"
0605     "date\n"
0606     "echo Script successfully ran\n"
0607     "date\n"
0608     "stackuse\n"
0609   );
0610 
0611   writeScript(
0612     "/scripts/j1",
0613     "#! joel -s 20480 -t JESS\n"
0614     "stackuse\n"
0615   );
0616 
0617   rtems_shell_write_file(
0618     "/scripts/j2",
0619     "echo j2 TEST FILE\n"
0620     "echo j2   SHOULD BE non-executable AND\n"
0621     "echo j2   DOES NOT have the magic first line\n"
0622   );
0623 
0624   rtems_shell_add_cmd ("mkrd", "files",
0625                        "Create a RAM disk driver", create_ramdisk);
0626   rtems_shell_add_cmd ("mknvd", "files",
0627                        "Create a NV disk driver", create_nvdisk);
0628   rtems_shell_add_cmd ("nverase", "misc",
0629                        "nverase driver", shell_nvdisk_erase);
0630   rtems_shell_add_cmd ("nvtrace", "misc",
0631                        "nvtrace driver level", shell_nvdisk_trace);
0632   rtems_shell_add_cmd ("bdbuftrace", "files",
0633                        "bdbuf trace toggle", shell_bdbuf_trace);
0634   rtems_shell_add_cmd ("td", "files",
0635                        "Test disk", disk_test_block_sizes);
0636 #if RTEMS_RFS_TRACE
0637   rtems_shell_add_cmd ("rfs", "files",
0638                        "RFS trace",
0639                        rtems_rfs_trace_shell_command);
0640 #endif
0641 #if RTEMS_RFS_RTEMS_TRACE
0642   rtems_shell_add_cmd ("rrfs", "files",
0643                        "RTEMS RFS trace",
0644                        rtems_rfs_rtems_trace_shell_command);
0645 #endif
0646 
0647   printf(" =========================\n");
0648   printf(" starting shell\n");
0649   printf(" =========================\n");
0650   rtems_shell_init(
0651     "SHLL",                          /* task_name */
0652     RTEMS_MINIMUM_STACK_SIZE * 5,    /* task_stacksize */
0653     100,                             /* task_priority */
0654     "/dev/foobar",                   /* devname */
0655     /* device is currently ignored by the shell if it is not a pty */
0656     false,                           /* forever */
0657     true,                            /* wait */
0658     rtems_shell_login_check          /* login */
0659   );
0660 }
0661 #endif /* USE_SHELL */
0662 
0663 static void fileio_print_free_heap(void)
0664 {
0665   printf("--- unused dynamic memory: %lu bytes ---\n",
0666      (unsigned long) malloc_free_space());
0667 }
0668 
0669 
0670 static void fileio_part_table_initialize(void)
0671 {
0672   char devname[64];
0673   rtems_status_code rc;
0674 
0675   printf(" =========================\n");
0676   printf(" Initialize partition table\n");
0677   printf(" =========================\n");
0678   fileio_print_free_heap();
0679   printf(" Enter device to initialize ==>");
0680   fflush(stdout);
0681   fgets(devname,sizeof(devname)-1,stdin);
0682   while (devname[strlen(devname)-1] == '\n') {
0683     devname[strlen(devname)-1] = '\0';
0684   }
0685   /*
0686    * call function
0687    */
0688   rc = rtems_bdpart_register_from_disk(devname);
0689   printf("result = %d\n",rc);
0690   fileio_print_free_heap();
0691 }
0692 
0693 static void fileio_fsmount(void)
0694 {
0695   rtems_status_code rc;
0696 
0697   printf(" =========================\n");
0698   printf(" Process fsmount table\n");
0699   printf(" =========================\n");
0700   fileio_print_free_heap();
0701   /*
0702    * call function
0703    */
0704   rc = rtems_fsmount( fs_table,
0705               sizeof(fs_table)/sizeof(fs_table[0]),
0706               NULL);
0707   printf("result = %d\n",rc);
0708   fileio_print_free_heap();
0709 }
0710 
0711 static void fileio_list_file(void)
0712 {
0713   char fname[1024];
0714   char *buf_ptr = NULL;
0715   ssize_t   flen = 0;
0716   int fd = -1;
0717   ssize_t n;
0718   size_t buf_size = 100;
0719 
0720   rtems_interval start_tick,curr_tick,ticks_per_sec;
0721 
0722   printf(" =========================\n");
0723   printf(" LIST FILE ...            \n");
0724   printf(" =========================\n");
0725   fileio_print_free_heap();
0726   printf(" Enter filename to list ==>");
0727   fflush(stdout);
0728   fgets(fname,sizeof(fname)-1,stdin);
0729   while (fname[strlen(fname)-1] == '\n') {
0730     fname[strlen(fname)-1] = '\0';
0731   }
0732   /*
0733    * allocate buffer of given size
0734    */
0735   if (buf_size > 0) {
0736     buf_ptr = malloc(buf_size);
0737   }
0738 
0739   if (buf_ptr != NULL) {
0740     printf("\n Trying to open file \"%s\" for read\n",fname);
0741     fd = open(fname,O_RDONLY);
0742     if (fd < 0) {
0743       printf("*** file failed to open, errno = %d(%s)\n",errno,strerror(errno));
0744     }
0745   }
0746 
0747   if (fd >= 0) {
0748     start_tick = rtems_clock_get_ticks_since_boot();
0749     do {
0750       n = read(fd,buf_ptr,buf_size);
0751       if (n > 0) {
0752     write(1,buf_ptr,(size_t) n);
0753     flen += n;
0754       }
0755     } while (n > 0);
0756 
0757     curr_tick = rtems_clock_get_ticks_since_boot();
0758 
0759     printf("\n ******** End of file reached, flen = %zd\n",flen);
0760     close(fd);
0761 
0762     ticks_per_sec = rtems_clock_get_ticks_per_second();
0763     printf("time elapsed for read:  %g seconds\n",
0764        ((double)curr_tick-start_tick)/ticks_per_sec);
0765   }
0766   /*
0767    * free buffer
0768    */
0769   if (buf_ptr != NULL) {
0770     free(buf_ptr);
0771   }
0772   fileio_print_free_heap();
0773 }
0774 
0775 /*
0776  * convert a size string (like 34K or 12M) to actual byte count
0777  */
0778 static bool fileio_str2size(const char *str,uint32_t   *res_ptr)
0779 {
0780   bool failed = false;
0781   unsigned long size;
0782   unsigned char suffix = ' ';
0783 
0784   if (1 > sscanf(str,"%lu%c",&size,&suffix)) {
0785     failed = true;
0786   }
0787   else if (toupper((int)suffix) == 'K') {
0788     size *= 1024;
0789   }
0790   else if (toupper((int)suffix) == 'M') {
0791     size *= 1024UL*1024UL;
0792   }
0793   else if (isalpha((int)suffix)) {
0794     failed = true;
0795   }
0796 
0797   if (!failed) {
0798     *res_ptr = size;
0799   }
0800   return failed;
0801 }
0802 
0803 static void fileio_write_file(void)
0804 {
0805   char fname[1024];
0806   char tmp_str[32];
0807   uint32_t   file_size = 0;
0808   uint32_t   buf_size  = 0;
0809   size_t curr_pos,bytes_to_copy;
0810   int fd = -1;
0811   ssize_t n;
0812   rtems_interval start_tick,curr_tick,ticks_per_sec;
0813   char *bufptr = NULL;
0814   bool failed = false;
0815   static const char write_test_string[] =
0816     "The quick brown fox jumps over the lazy dog\n";
0817   static const char write_block_string[] =
0818     "\n----- end of write buffer ------\n";
0819 
0820   printf(" =========================\n");
0821   printf(" WRITE FILE ...           \n");
0822   printf(" =========================\n");
0823   fileio_print_free_heap();
0824   /*
0825    * get number of ticks per second
0826    */
0827   ticks_per_sec = rtems_clock_get_ticks_per_second();
0828 
0829   /*
0830    * get path to file to write
0831    */
0832   if (!failed) {
0833     printf("Enter path/filename ==>");
0834     fflush(stdout);
0835     fgets(fname,sizeof(fname)-1,stdin);
0836     while (fname[strlen(fname)-1] == '\n') {
0837       fname[strlen(fname)-1] = '\0';
0838     }
0839     if (0 == strlen(fname)) {
0840       printf("*** no filename entered, aborted\n");
0841       failed = true;
0842     }
0843   }
0844   /*
0845    * get total file size to write
0846    */
0847   if (!failed) {
0848     printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
0849        "Enter filesize to write ==>");
0850     fflush(stdout);
0851     fgets(tmp_str,sizeof(tmp_str)-1,stdin);
0852     failed = fileio_str2size(tmp_str,&file_size);
0853     if (failed) {
0854       printf("*** illegal file size, aborted\n");
0855     }
0856   }
0857   /*
0858    * get block size to write
0859    */
0860   if (!failed) {
0861     printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
0862        "Enter block size to use for write calls ==>");
0863     fflush(stdout);
0864     fgets(tmp_str,sizeof(tmp_str)-1,stdin);
0865     failed = fileio_str2size(tmp_str,&buf_size);
0866     if (failed) {
0867       printf("*** illegal block size, aborted\n");
0868     }
0869   }
0870 
0871   /*
0872    * allocate buffer
0873    */
0874   if (!failed) {
0875     printf("... allocating %lu bytes of buffer for write data\n",
0876        (unsigned long)buf_size);
0877     bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
0878     if (bufptr == NULL) {
0879       printf("*** malloc failed, aborted\n");
0880       failed = true;
0881     }
0882   }
0883   /*
0884    * fill buffer with test pattern
0885    */
0886   if (!failed) {
0887     printf("... filling buffer with write data\n");
0888     curr_pos = 0;
0889     /*
0890      * fill buffer with test string
0891      */
0892     while (curr_pos < buf_size) {
0893       bytes_to_copy = MIN(buf_size-curr_pos,
0894               sizeof(write_test_string)-1);
0895       memcpy(bufptr+curr_pos,write_test_string,bytes_to_copy);
0896       curr_pos += bytes_to_copy;
0897     }
0898     /*
0899      * put "end" mark at end of buffer
0900      */
0901     bytes_to_copy = sizeof(write_block_string)-1;
0902     if (buf_size >= bytes_to_copy) {
0903       memcpy(bufptr+buf_size-bytes_to_copy,
0904          write_block_string,
0905          bytes_to_copy);
0906     }
0907   }
0908   /*
0909    * create file
0910    */
0911   if (!failed) {
0912     printf("... creating file \"%s\"\n",fname);
0913     fd = open(fname,O_WRONLY | O_CREAT | O_TRUNC,S_IREAD|S_IWRITE);
0914     if (fd < 0) {
0915       printf("*** file create failed, errno = %d(%s)\n",errno,strerror(errno));
0916       failed = true;
0917     }
0918   }
0919   /*
0920    * write file
0921    */
0922   if (!failed) {
0923     printf("... writing to file\n");
0924     start_tick = rtems_clock_get_ticks_since_boot();
0925     curr_pos = 0;
0926     do {
0927       bytes_to_copy = buf_size;
0928       do {
0929     n = write(fd,
0930       bufptr + (buf_size-bytes_to_copy),
0931           MIN(bytes_to_copy,file_size-curr_pos));
0932     if (n > 0) {
0933       bytes_to_copy -= (size_t) n;
0934       curr_pos      += (size_t) n;
0935     }
0936       } while ((bytes_to_copy > 0)  && (n > 0));
0937     } while ((file_size > curr_pos) && (n > 0));
0938     curr_tick = rtems_clock_get_ticks_since_boot();
0939     if (n < 0) {
0940       failed = true;
0941       printf("*** file write failed, "
0942          "%lu bytes written, "
0943          "errno = %d(%s)\n",
0944          (unsigned long)curr_pos,errno,strerror(errno));
0945     }
0946     else {
0947       printf("time elapsed for write:  %g seconds\n",
0948          ((double)curr_tick-start_tick)/ticks_per_sec);
0949       printf("write data rate: %g KBytes/second\n",
0950          (((double)file_size) / 1024.0 /
0951           (((double)curr_tick-start_tick)/ticks_per_sec)));
0952     }
0953   }
0954   if (fd >= 0) {
0955     printf("... closing file\n");
0956     close(fd);
0957   }
0958   if (bufptr != NULL) {
0959     printf("... deallocating buffer\n");
0960     free(bufptr);
0961     bufptr = NULL;
0962   }
0963   printf("\n ******** End of file write\n");
0964   fileio_print_free_heap();
0965 }
0966 
0967 static void fileio_read_file(void)
0968 {
0969   char fname[1024];
0970   char tmp_str[32];
0971   uint32_t   buf_size  = 0;
0972   size_t curr_pos;
0973   int fd = -1;
0974   ssize_t n;
0975   rtems_interval start_tick,curr_tick,ticks_per_sec;
0976   char *bufptr = NULL;
0977   bool failed = false;
0978 
0979   printf(" =========================\n");
0980   printf(" READ FILE ...            \n");
0981   printf(" =========================\n");
0982   fileio_print_free_heap();
0983   /*
0984    * get number of ticks per second
0985    */
0986   ticks_per_sec = rtems_clock_get_ticks_per_second();
0987 
0988   /*
0989    * get path to file to read
0990    */
0991   if (!failed) {
0992     printf("Enter path/filename ==>");
0993     fflush(stdout);
0994     fgets(fname,sizeof(fname)-1,stdin);
0995     while (fname[strlen(fname)-1] == '\n') {
0996       fname[strlen(fname)-1] = '\0';
0997     }
0998     if (0 == strlen(fname)) {
0999       printf("*** no filename entered, aborted\n");
1000       failed = true;
1001     }
1002   }
1003   /*
1004    * get block size to read
1005    */
1006   if (!failed) {
1007     printf("use suffix K for Kbytes, M for Mbytes or no suffix for bytes:\n"
1008        "Enter block size to use for read calls ==>");
1009     fflush(stdout);
1010     fgets(tmp_str,sizeof(tmp_str)-1,stdin);
1011     failed = fileio_str2size(tmp_str,&buf_size);
1012     if (failed) {
1013       printf("*** illegal block size, aborted\n");
1014     }
1015   }
1016 
1017   /*
1018    * allocate buffer
1019    */
1020   if (!failed) {
1021     printf("... allocating %lu bytes of buffer for write data\n",
1022        (unsigned long)buf_size);
1023     bufptr = malloc(buf_size+1); /* extra space for terminating NUL char */
1024     if (bufptr == NULL) {
1025       printf("*** malloc failed, aborted\n");
1026       failed = true;
1027     }
1028   }
1029   /*
1030    * open file
1031    */
1032   if (!failed) {
1033     printf("... opening file \"%s\"\n",fname);
1034     fd = open(fname,O_RDONLY);
1035     if (fd < 0) {
1036       printf("*** failed to open file, errno = %d(%s)\n",errno,strerror(errno));
1037       failed = true;
1038     }
1039   }
1040   /*
1041    * read file
1042    */
1043   if (!failed) {
1044     printf("... reading from file\n");
1045     start_tick = rtems_clock_get_ticks_since_boot();
1046     curr_pos = 0;
1047     do {
1048       n = read(fd,
1049            bufptr,
1050            buf_size);
1051       if (n > 0) {
1052     curr_pos      += (size_t) n;
1053       }
1054     } while (n > 0);
1055     curr_tick = rtems_clock_get_ticks_since_boot();
1056     if (n < 0) {
1057       failed = true;
1058       printf("*** file read failed, "
1059          "%lu bytes read, "
1060          "errno = %d(%s)\n",
1061          (unsigned long)curr_pos,errno,strerror(errno));
1062     }
1063     else {
1064       printf("%lu bytes read\n",
1065          (unsigned long)curr_pos);
1066       printf("time elapsed for read:  %g seconds\n",
1067          ((double)curr_tick-start_tick)/ticks_per_sec);
1068       printf("read data rate: %g KBytes/second\n",
1069          (((double)curr_pos) / 1024.0 /
1070           (((double)curr_tick-start_tick)/ticks_per_sec)));
1071     }
1072   }
1073   if (fd >= 0) {
1074     printf("... closing file\n");
1075     close(fd);
1076   }
1077   if (bufptr != NULL) {
1078     printf("... deallocating buffer\n");
1079     free(bufptr);
1080     bufptr = NULL;
1081   }
1082   printf("\n ******** End of file read\n");
1083   fileio_print_free_heap();
1084 
1085 }
1086 
1087 static void fileio_menu (void)
1088 {
1089   char inbuf[10];
1090 
1091   /*
1092    * Wait for characters from console terminal
1093    */
1094   for (;;) {
1095     printf(" =========================\n");
1096     printf(" RTEMS FILE I/O Test Menu \n");
1097     printf(" =========================\n");
1098     printf("   p -> part_table_initialize\n");
1099     printf("   f -> mount all disks in fs_table\n");
1100     printf("   l -> list  file\n");
1101     printf("   r -> read  file\n");
1102     printf("   w -> write file\n");
1103 #ifdef USE_SHELL
1104     printf("   s -> start shell\n");
1105 #endif
1106     printf("   Enter your selection ==>");
1107     fflush(stdout);
1108 
1109     inbuf[0] = '\0';
1110     fgets(inbuf,sizeof(inbuf),stdin);
1111     switch (inbuf[0]) {
1112     case 'l':
1113       fileio_list_file ();
1114       break;
1115     case 'r':
1116       fileio_read_file ();
1117       break;
1118     case 'w':
1119       fileio_write_file ();
1120       break;
1121     case 'p':
1122       fileio_part_table_initialize ();
1123       break;
1124     case 'f':
1125       fileio_fsmount ();
1126       break;
1127 #ifdef USE_SHELL
1128     case 's':
1129       fileio_start_shell ();
1130       break;
1131 #endif
1132     default:
1133       printf("Selection `%c` not implemented\n",inbuf[0]);
1134       break;
1135     }
1136 
1137   }
1138   exit (0);
1139 }
1140 
1141 /*
1142  * RTEMS File Menu Task
1143  */
1144 static rtems_task
1145 fileio_task (rtems_task_argument ignored)
1146 {
1147   fileio_menu();
1148 }
1149 
1150 static void
1151 notification (int fd, int seconds_remaining, void *arg)
1152 {
1153   printf(
1154     "Press any key to start file I/O sample (%is remaining)\n",
1155     seconds_remaining
1156   );
1157 }
1158 
1159 /*
1160  * RTEMS Startup Task
1161  */
1162 rtems_task
1163 Init (rtems_task_argument ignored)
1164 {
1165   rtems_name Task_name;
1166   rtems_id   Task_id;
1167   rtems_status_code status;
1168 
1169   TEST_BEGIN();
1170 
1171   crypt_add_format(&crypt_md5_format);
1172   crypt_add_format(&crypt_sha512_format);
1173 
1174   status = rtems_shell_wait_for_input(
1175     STDIN_FILENO,
1176     20,
1177     notification,
1178     NULL
1179   );
1180   if (status == RTEMS_SUCCESSFUL) {
1181     Task_name = rtems_build_name('F','M','N','U');
1182 
1183     status = rtems_task_create(
1184       Task_name, 1, RTEMS_MINIMUM_STACK_SIZE * 2,
1185       RTEMS_DEFAULT_MODES ,
1186       RTEMS_FLOATING_POINT | RTEMS_DEFAULT_ATTRIBUTES, &Task_id
1187     );
1188     directive_failed( status, "create" ); 
1189 
1190     status = rtems_task_start( Task_id, fileio_task, 1 );
1191     directive_failed( status, "start" ); 
1192 
1193     rtems_task_exit();
1194   } else {
1195     TEST_END();
1196 
1197     rtems_test_exit( 0 );
1198   }
1199 }
1200 
1201 #if defined(USE_SHELL)
1202 /*
1203  *  RTEMS Shell Configuration -- Add a command and an alias for it
1204  */
1205 
1206 static int main_usercmd(int argc, char **argv)
1207 {
1208   int i;
1209   printf( "UserCommand: argc=%d\n", argc );
1210   for (i=0 ; i<argc ; i++ )
1211     printf( "argv[%d]= %s\n", i, argv[i] );
1212   return 0;
1213 }
1214 
1215 static rtems_shell_cmd_t Shell_USERCMD_Command = {
1216   "usercmd",                                       /* name */
1217   "usercmd n1 [n2 [n3...]]     # echo arguments",  /* usage */
1218   "user",                                          /* topic */
1219   main_usercmd,                                    /* command */
1220   NULL,                                            /* alias */
1221   NULL                                             /* next */
1222 };
1223 
1224 static rtems_shell_alias_t Shell_USERECHO_Alias = {
1225   "usercmd",                 /* command */
1226   "userecho"                 /* alias */
1227 };
1228 
1229 
1230 #define CONFIGURE_SHELL_USER_COMMANDS &Shell_USERCMD_Command
1231 #define CONFIGURE_SHELL_USER_ALIASES &Shell_USERECHO_Alias
1232 #define CONFIGURE_SHELL_COMMANDS_INIT
1233 #define CONFIGURE_SHELL_COMMANDS_ALL
1234 #define CONFIGURE_SHELL_MOUNT_MSDOS
1235 #define CONFIGURE_SHELL_MOUNT_RFS
1236 #define CONFIGURE_SHELL_DEBUGRFS
1237 
1238 #include <rtems/shellconfig.h>
1239 #endif
1240 
1241 #else
1242 /*
1243  * RTEMS Startup Task
1244  */
1245 rtems_task
1246 Init (rtems_task_argument ignored)
1247 {
1248   puts( "\n\n*** FILE I/O SAMPLE AND TEST ***" );
1249   puts( "\n\n*** NOT ENOUGH MEMORY TO BUILD AND RUN ***" );
1250 }
1251 #endif