source: rtems/c/src/lib/libbsp/arm/gdbarmsim/startup/syscalls.c @ 44bb5cd0

4.104.115
Last change on this file since 44bb5cd0 was 44bb5cd0, checked in by Joel Sherrill <joel.sherrill@…>, on 10/01/09 at 21:48:42

2009-10-01 Joel Sherrill <joel.sherrill@…>

  • .cvsignore, ChangeLog?, Makefile.am, bsp_specs, configure.ac, preinstall.am, console/.cvsignore, console/console-io.c, include/.cvsignore, include/bsp.h, include/irq.h, include/swi.h, start/.cvsignore, start/start.S, startup/.cvsignore, startup/bspreset.c, startup/bspstart.c, startup/linkcmds, startup/syscalls.c: New files.
  • Property mode set to 100644
File size: 17.6 KB
Line 
1/*
2 *  Copied from libgloss 1 Oct 2009.
3 *  Minor modifications to work with RTEMS.
4 *
5 *  $Id$
6 */
7
8/* Support files for GNU libc.  Files in the system namespace go here.
9   Files in the C namespace (ie those that do not start with an
10   underscore) go in .c.  */
11
12#include <_ansi.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <sys/fcntl.h>
16#include <stdio.h>
17#include <string.h>
18#include <time.h>
19#include <sys/time.h>
20#include <sys/times.h>
21#include <errno.h>
22#include <reent.h>
23#include <unistd.h>
24#include <sys/wait.h>
25#include <bsp/swi.h>
26
27/* Forward prototypes.  */
28int     _system     _PARAMS ((const char *));
29int     _rename     _PARAMS ((const char *, const char *));
30int     _isatty         _PARAMS ((int));
31clock_t _times          _PARAMS ((struct tms *));
32int     _gettimeofday   _PARAMS ((struct timeval *, void *));
33int     _unlink         _PARAMS ((const char *));
34int     _link           _PARAMS ((void));
35int     _stat           _PARAMS ((const char *, struct stat *));
36int     _fstat          _PARAMS ((int, struct stat *));
37int     _swistat        _PARAMS ((int fd, struct stat * st));
38caddr_t _sbrk           _PARAMS ((int));
39int     _getpid         _PARAMS ((int));
40int     _close          _PARAMS ((int));
41clock_t _clock          _PARAMS ((void));
42int     _swiclose       _PARAMS ((int));
43int     _open           _PARAMS ((const char *, int, ...));
44int     _swiopen        _PARAMS ((const char *, int));
45int     _write          _PARAMS ((int, char *, int));
46int     _swiwrite       _PARAMS ((int, char *, int));
47int     _lseek          _PARAMS ((int, int, int));
48int     _swilseek       _PARAMS ((int, int, int));
49int     _read           _PARAMS ((int, char *, int));
50int     _swiread        _PARAMS ((int, char *, int));
51void    initialise_monitor_handles _PARAMS ((void));
52
53static int      checkerror      _PARAMS ((int));
54static int      error           _PARAMS ((int));
55static int      get_errno       _PARAMS ((void));
56
57/* Struct used to keep track of the file position, just so we
58   can implement fseek(fh,x,SEEK_CUR).  */
59struct fdent
60{
61  int handle;
62  int pos;
63};
64
65#define MAX_OPEN_FILES 20
66
67/* User file descriptors (fd) are integer indexes into
68   the openfiles[] array. Error checking is done by using
69   findslot().
70
71   This openfiles array is manipulated directly by only
72   these 5 functions:
73
74        findslot() - Translate entry.
75        newslot() - Find empty entry.
76        initilise_monitor_handles() - Initialize entries.
77        _swiopen() - Initialize entry.
78        _close() - Handle stdout == stderr case.
79
80   Every other function must use findslot().  */
81
82static struct fdent openfiles [MAX_OPEN_FILES];
83
84static struct fdent*    findslot        _PARAMS ((int));
85static int              newslot         _PARAMS ((void));
86
87/* Register name faking - works in collusion with the linker.  */
88register char * stack_ptr asm ("sp");
89
90
91/* following is copied from libc/stdio/local.h to check std streams */
92extern void   _EXFUN(__sinit,(struct _reent *));
93#define CHECK_INIT(ptr) \
94  do                                            \
95    {                                           \
96      if ((ptr) && !(ptr)->__sdidinit)          \
97        __sinit (ptr);                          \
98    }                                           \
99  while (0)
100
101static int monitor_stdin;
102static int monitor_stdout;
103static int monitor_stderr;
104
105/* Return a pointer to the structure associated with
106   the user file descriptor fd. */
107static struct fdent*
108findslot (int fd)
109{
110  CHECK_INIT(_REENT);
111
112  /* User file descriptor is out of range. */
113  if ((unsigned int)fd >= MAX_OPEN_FILES)
114    return NULL;
115
116  /* User file descriptor is open? */
117  if (openfiles[fd].handle == -1)
118    return NULL;
119
120  /* Valid. */
121  return &openfiles[fd];
122}
123
124/* Return the next lowest numbered free file
125   structure, or -1 if we can't find one. */
126static int
127newslot (void)
128{
129  int i;
130
131  for (i = 0; i < MAX_OPEN_FILES; i++)
132    if (openfiles[i].handle == -1)
133      break;
134
135  if (i == MAX_OPEN_FILES)
136    return -1;
137
138  return i;
139}
140
141void
142initialise_monitor_handles (void)
143{
144  int i;
145 
146  /* Open the standard file descriptors by opening the special
147   * teletype device, ":tt", read-only to obtain a descritpor for
148   * standard input and write-only to obtain a descriptor for standard
149   * output. Finally, open ":tt" in append mode to obtain a descriptor
150   * for standard error. Since this is a write mode, most kernels will
151   * probably return the same value as for standard output, but the
152   * kernel can differentiate the two using the mode flag and return a
153   * different descriptor for standard error.
154   */
155
156#ifdef ARM_RDI_MONITOR
157  int volatile block[3];
158 
159  block[0] = (int) ":tt";
160  block[2] = 3;     /* length of filename */
161  block[1] = 0;     /* mode "r" */
162  monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
163
164  block[0] = (int) ":tt";
165  block[2] = 3;     /* length of filename */
166  block[1] = 4;     /* mode "w" */
167  monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
168
169  block[0] = (int) ":tt";
170  block[2] = 3;     /* length of filename */
171  block[1] = 8;     /* mode "a" */
172  monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
173#else
174  int fh;
175  const char * name;
176
177  name = ":tt";
178  asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0"
179       : "=r"(fh)
180       : "i" (SWI_Open),"r"(name)
181       : "r0","r1");
182  monitor_stdin = fh;
183
184  name = ":tt";
185  asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
186       : "=r"(fh)
187       : "i" (SWI_Open),"r"(name)
188       : "r0","r1");
189  monitor_stdout = fh;
190
191  name = ":tt";
192  asm ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
193       : "=r"(fh)
194       : "i" (SWI_Open),"r"(name)
195       : "r0","r1");
196  monitor_stderr = fh;
197#endif
198
199  /* If we failed to open stderr, redirect to stdout. */
200  if (monitor_stderr == -1)
201    monitor_stderr = monitor_stdout;
202
203  for (i = 0; i < MAX_OPEN_FILES; i ++)
204    openfiles[i].handle = -1;
205
206  openfiles[0].handle = monitor_stdin;
207  openfiles[0].pos = 0;
208  openfiles[1].handle = monitor_stdout;
209  openfiles[1].pos = 0;
210  openfiles[2].handle = monitor_stderr;
211  openfiles[2].pos = 0;
212}
213
214static int
215get_errno (void)
216{
217#ifdef ARM_RDI_MONITOR
218  return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
219#else
220  register int r0 asm("r0");
221  asm ("swi %a1" : "=r"(r0) : "i" (SWI_GetErrno));
222  return r0;
223#endif
224}
225
226/* Set errno and return result. */
227static int
228error (int result)
229{
230  errno = get_errno ();
231  return result;
232}
233
234/* Check the return and set errno appropriately. */
235static int
236checkerror (int result)
237{
238  if (result == -1)
239    return error (-1);
240  return result;
241}
242
243/* fh, is a valid internal file handle.
244   ptr, is a null terminated string.
245   len, is the length in bytes to read.
246   Returns the number of bytes *not* written. */
247int
248_swiread (int fh,
249          char * ptr,
250          int len)
251{
252#ifdef ARM_RDI_MONITOR
253  int block[3];
254 
255  block[0] = fh;
256  block[1] = (int) ptr;
257  block[2] = len;
258 
259  return checkerror (do_AngelSWI (AngelSWI_Reason_Read, block));
260#else
261  register int r0 asm("r0");
262  register int r1 asm("r1");
263  register int r2 asm("r2");
264  r0 = fh;
265  r1 = (int)ptr;
266  r2 = len;
267  asm ("swi %a4"
268       : "=r" (r0)
269       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read));
270  return checkerror (r0);
271#endif
272}
273
274/* fd, is a valid user file handle.
275   Translates the return of _swiread into
276   bytes read. */
277int
278_read (int fd,
279       char * ptr,
280       int len)
281{
282  int res;
283  struct fdent *pfd;
284
285  pfd = findslot (fd);
286  if (pfd == NULL)
287    {
288      errno = EBADF;
289      return -1;
290    }
291
292  res = _swiread (pfd->handle, ptr, len);
293
294  if (res == -1)
295    return res;
296
297  pfd->pos += len - res;
298
299  /* res == len is not an error,
300     at least if we want feof() to work.  */
301  return len - res;
302}
303
304/* fd, is a user file descriptor. */
305int
306_swilseek (int fd,
307        int ptr,
308        int dir)
309{
310  int res;
311  struct fdent *pfd;
312
313  /* Valid file descriptor? */
314  pfd = findslot (fd);
315  if (pfd == NULL)
316    {
317      errno = EBADF;
318      return -1;
319    }
320
321  /* Valid whence? */
322  if ((dir != SEEK_CUR)
323      && (dir != SEEK_SET)
324      && (dir != SEEK_END))
325    {
326      errno = EINVAL;
327      return -1;
328    }
329
330  /* Convert SEEK_CUR to SEEK_SET */
331  if (dir == SEEK_CUR)
332    {
333      ptr = pfd->pos + ptr;
334      /* The resulting file offset would be negative. */
335      if (ptr < 0)
336        {
337          errno = EINVAL;
338          if ((pfd->pos > 0) && (ptr > 0))
339            errno = EOVERFLOW;
340          return -1;
341        }
342      dir = SEEK_SET;
343    }
344 
345#ifdef ARM_RDI_MONITOR
346  int block[2];
347  if (dir == SEEK_END)
348    {
349      block[0] = pfd->handle;
350      res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, block));
351      if (res == -1)
352        return -1;
353      ptr += res;
354    }
355 
356  /* This code only does absolute seeks.  */
357  block[0] = pfd->handle;
358  block[1] = ptr;
359  res = checkerror (do_AngelSWI (AngelSWI_Reason_Seek, block));
360#else
361  if (dir == SEEK_END)
362    {
363      asm ("mov r0, %2; swi %a1; mov %0, r0"
364           : "=r" (res)
365           : "i" (SWI_Flen), "r" (pfd->handle)
366           : "r0");
367      checkerror (res);
368      if (res == -1)
369        return -1;
370      ptr += res;
371    }
372
373  /* This code only does absolute seeks.  */
374  asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
375       : "=r" (res)
376       : "i" (SWI_Seek), "r" (pfd->handle), "r" (ptr)
377       : "r0", "r1");
378  checkerror (res);
379#endif
380  /* At this point ptr is the current file position. */
381  if (res >= 0)
382    {
383      pfd->pos = ptr;
384      return ptr;
385    }
386  else
387    return -1;
388}
389
390int
391_lseek (int fd,
392        int ptr,
393        int dir)
394{
395  return _swilseek (fd, ptr, dir);
396}
397
398/* fh, is a valid internal file handle.
399   Returns the number of bytes *not* written. */
400int
401_swiwrite (
402           int    fh,
403           char * ptr,
404           int    len)
405{
406#ifdef ARM_RDI_MONITOR
407  int block[3];
408 
409  block[0] = fh;
410  block[1] = (int) ptr;
411  block[2] = len;
412 
413  return checkerror (do_AngelSWI (AngelSWI_Reason_Write, block));
414#else
415  register int r0 asm("r0");
416  register int r1 asm("r1");
417  register int r2 asm("r2");
418  r0 = fh;
419  r1 = (int)ptr;
420  r2 = len;
421  asm ("swi %a4"
422       : "=r" (r0)
423       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Write));
424  return checkerror (r0);
425#endif
426}
427
428/* fd, is a user file descriptor. */
429int
430_write (int    fd,
431        char * ptr,
432        int    len)
433{
434  int res;
435  struct fdent *pfd;
436
437  pfd = findslot (fd);
438  if (pfd == NULL)
439    {
440      errno = EBADF;
441      return -1;
442    }
443
444  res = _swiwrite (pfd->handle, ptr,len);
445
446  /* Clearly an error. */
447  if (res < 0)
448    return -1;
449
450  pfd->pos += len - res;
451
452  /* We wrote 0 bytes?
453     Retrieve errno just in case. */
454  if ((len - res) == 0)
455    return error (0);
456 
457  return (len - res);
458}
459
460int
461_swiopen (const char * path, int flags)
462{
463  int aflags = 0, fh;
464#ifdef ARM_RDI_MONITOR
465  int block[3];
466#endif
467 
468  int fd = newslot ();
469
470  if (fd == -1)
471    {
472      errno = EMFILE;
473      return -1;
474    }
475 
476  /* It is an error to open a file that already exists. */
477  if ((flags & O_CREAT)
478      && (flags & O_EXCL))
479    {
480      struct stat st;
481      int res;
482      res = _stat (path, &st);
483      if (res != -1)
484        {
485          errno = EEXIST;
486          return -1;
487        }
488    }
489
490  /* The flags are Unix-style, so we need to convert them. */
491#ifdef O_BINARY
492  if (flags & O_BINARY)
493    aflags |= 1;
494#endif
495 
496  /* In O_RDONLY we expect aflags == 0. */
497
498  if (flags & O_RDWR)
499    aflags |= 2;
500
501  if ((flags & O_CREAT)
502      || (flags & O_TRUNC)
503      || (flags & O_WRONLY))
504    aflags |= 4;
505
506  if (flags & O_APPEND)
507    {
508      /* Can't ask for w AND a; means just 'a'.  */
509      aflags &= ~4;
510      aflags |= 8;
511    }
512 
513#ifdef ARM_RDI_MONITOR
514  block[0] = (int) path;
515  block[2] = strlen (path);
516  block[1] = aflags;
517 
518  fh = do_AngelSWI (AngelSWI_Reason_Open, block);
519 
520#else
521  asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0"
522       : "=r"(fh)
523       : "i" (SWI_Open),"r"(path),"r"(aflags)
524       : "r0","r1");
525#endif
526 
527  /* Return a user file descriptor or an error. */
528  if (fh >= 0)
529    {
530      openfiles[fd].handle = fh;
531      openfiles[fd].pos = 0;
532      return fd;
533    }
534  else
535    return error (fh);
536}
537
538int
539_open (const char * path, int flags, ...)
540{
541  return _swiopen (path, flags);
542}
543
544/* fh, is a valid internal file handle. */
545int
546_swiclose (int fh)
547{
548#ifdef ARM_RDI_MONITOR
549  return checkerror (do_AngelSWI (AngelSWI_Reason_Close, &fh));
550#else
551  register int r0 asm("r0");
552  r0 = fh;
553  asm ("swi %a2"
554       : "=r"(r0)
555       : "0"(r0), "i" (SWI_Close));
556  return checkerror (r0);
557#endif
558}
559
560/* fd, is a user file descriptor. */
561int
562_close (int fd)
563{
564  int res;
565  struct fdent *pfd;
566
567  pfd = findslot (fd);
568  if (pfd == NULL)
569    {
570      errno = EBADF;
571      return -1;
572    }
573
574  /* Handle stderr == stdout. */
575  if ((fd == 1 || fd == 2)
576      && (openfiles[1].handle == openfiles[2].handle))
577    {
578      pfd->handle = -1;
579      return 0;
580    }
581
582  /* Attempt to close the handle. */
583  res = _swiclose (pfd->handle);
584
585  /* Reclaim handle? */
586  if (res == 0)
587    pfd->handle = -1;
588
589  return res;
590}
591
592int __attribute__((weak))
593_getpid (int n __attribute__ ((unused)))
594{
595  return 1;
596}
597
598#if !defined(__rtems__)
599caddr_t
600_sbrk (int incr)
601{
602  extern char end asm ("end"); /* Defined by the linker.  */
603  static char * heap_end;
604  char * prev_heap_end;
605
606  if (heap_end == NULL)
607    heap_end = & end;
608 
609  prev_heap_end = heap_end;
610 
611  if (heap_end + incr > stack_ptr)
612    {
613      /* Some of the libstdc++-v3 tests rely upon detecting
614         out of memory errors, so do not abort here.  */
615#if 0
616      extern void abort (void);
617
618      _write (1, "_sbrk: Heap and stack collision\n", 32);
619     
620      abort ();
621#else
622      errno = ENOMEM;
623      return (caddr_t) -1;
624#endif
625    }
626 
627  heap_end += incr;
628
629  return (caddr_t) prev_heap_end;
630}
631#endif
632
633int
634_swistat (int fd, struct stat * st)
635{
636  struct fdent *pfd;
637  int res;
638
639  pfd = findslot (fd);
640  if (pfd == NULL)
641    {
642      errno = EBADF;
643      return -1;
644    }
645
646  /* Always assume a character device,
647     with 1024 byte blocks. */
648  st->st_mode |= S_IFCHR;
649  st->st_blksize = 1024;
650#ifdef ARM_RDI_MONITOR
651  res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
652#else
653  asm ("mov r0, %2; swi %a1; mov %0, r0"
654       : "=r" (res)
655       : "i" (SWI_Flen), "r" (pfd->handle)
656       : "r0");
657  checkerror (res);
658#endif
659  if (res == -1)
660    return -1;
661  /* Return the file size. */
662  st->st_size = res;
663  return 0;
664}
665
666int __attribute__((weak))
667_fstat (int fd, struct stat * st)
668{
669  memset (st, 0, sizeof (* st));
670  return _swistat (fd, st);
671}
672
673int __attribute__((weak))
674_stat (const char *fname, struct stat *st)
675{
676  int fd, res;
677  memset (st, 0, sizeof (* st));
678  /* The best we can do is try to open the file readonly. 
679     If it exists, then we can guess a few things about it. */
680  if ((fd = _open (fname, O_RDONLY)) == -1)
681    return -1;
682  st->st_mode |= S_IFREG | S_IREAD;
683  res = _swistat (fd, st);
684  /* Not interested in the error. */
685  _close (fd);
686  return res;
687}
688
689int __attribute__((weak))
690_link (void)
691{
692  errno = ENOSYS;
693  return -1;
694}
695
696int
697_unlink (const char *path)
698{
699  int res;
700#ifdef ARM_RDI_MONITOR
701  int block[2];
702  block[0] = (int)path;
703  block[1] = strlen(path);
704  res = do_AngelSWI (AngelSWI_Reason_Remove, block);
705#else
706  register int r0 asm("r0");
707  r0 = (int)path;
708  asm ("swi %a2"
709       : "=r"(r0)
710       : "0"(r0), "i" (SWI_Remove));
711  res = r0;
712#endif
713  if (res == -1)
714    return error (res);
715  return 0;
716}
717
718#if !defined(__rtems__)
719int
720_gettimeofday (struct timeval * tp, void * tzvp)
721{
722  struct timezone *tzp = tzvp;
723  if (tp)
724    {
725    /* Ask the host for the seconds since the Unix epoch.  */
726#ifdef ARM_RDI_MONITOR
727      tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);
728#else
729      {
730        int value;
731        asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0");
732        tp->tv_sec = value;
733      }
734#endif
735      tp->tv_usec = 0;
736    }
737
738  /* Return fixed data for the timezone.  */
739  if (tzp)
740    {
741      tzp->tz_minuteswest = 0;
742      tzp->tz_dsttime = 0;
743    }
744
745  return 0;
746}
747#endif
748
749/* Return a clock that ticks at 100Hz.  */
750clock_t
751_clock (void)
752{
753  clock_t timeval;
754
755#ifdef ARM_RDI_MONITOR
756  timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);
757#else
758  asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");
759#endif
760  return timeval;
761}
762
763/* Return a clock that ticks at 100Hz.  */
764clock_t
765_times (struct tms * tp)
766{
767  clock_t timeval = _clock();
768
769  if (tp)
770    {
771      tp->tms_utime  = timeval; /* user time */
772      tp->tms_stime  = 0;       /* system time */
773      tp->tms_cutime = 0;       /* user time, children */
774      tp->tms_cstime = 0;       /* system time, children */
775    }
776 
777  return timeval;
778};
779
780
781int
782_isatty (int fd)
783{
784  struct fdent *pfd;
785
786  pfd = findslot (fd);
787  if (pfd == NULL)
788    {
789      errno = EBADF;
790      return -1;
791    }
792
793#ifdef ARM_RDI_MONITOR
794  return checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle));
795#else
796  register int r0 asm("r0");
797  r0 = pfd->handle;
798  asm ("swi %a2"
799       : "=r" (r0)
800       : "0"(r0), "i" (SWI_IsTTY));
801  return checkerror (r0);
802#endif
803}
804
805int
806_system (const char *s)
807{
808#ifdef ARM_RDI_MONITOR
809  int block[2];
810  int e;
811
812  /* Hmmm.  The ARM debug interface specification doesn't say whether
813     SYS_SYSTEM does the right thing with a null argument, or assign any
814     meaning to its return value.  Try to do something reasonable....  */
815  if (!s)
816    return 1;  /* maybe there is a shell available? we can hope. :-P */
817  block[0] = (int)s;
818  block[1] = strlen (s);
819  e = checkerror (do_AngelSWI (AngelSWI_Reason_System, block));
820  if ((e >= 0) && (e < 256))
821    {
822      /* We have to convert e, an exit status to the encoded status of
823         the command.  To avoid hard coding the exit status, we simply
824         loop until we find the right position.  */
825      int exit_code;
826
827      for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
828        continue;
829    }
830  return e;
831#else
832  register int r0 asm("r0");
833  r0 = (int)s;
834  asm ("swi %a2"
835       : "=r" (r0)
836       : "0"(r0), "i" (SWI_CLI));
837  return checkerror (r0);
838#endif
839}
840
841int
842_rename (const char * oldpath, const char * newpath)
843{
844#ifdef ARM_RDI_MONITOR
845  int block[4];
846  block[0] = (int)oldpath;
847  block[1] = strlen(oldpath);
848  block[2] = (int)newpath;
849  block[3] = strlen(newpath);
850  return checkerror (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
851#else
852  register int r0 asm("r0");
853  register int r1 asm("r1");
854  r0 = (int)oldpath;
855  r1 = (int)newpath;
856  asm ("swi %a3"
857       : "=r" (r0)
858       : "0" (r0), "r" (r1), "i" (SWI_Rename));
859  return checkerror (r0);
860#endif
861}
Note: See TracBrowser for help on using the repository browser.