Nano102_112 Series BSP  V3.03.002
The Board Support Package for Nano102_112 Series
_syscalls.c
Go to the documentation of this file.
1 //
2 // This file is part of the uOS++ III distribution
3 // Parts of this file are from the newlib sources, issued under GPL.
4 // Copyright (c) 2014 Liviu Ionescu
5 //
6 
7 // ----------------------------------------------------------------------------
8 
9 int errno;
10 void *__dso_handle __attribute__ ((weak));
11 
12 // ----------------------------------------------------------------------------
13 
14 #if !defined(OS_USE_SEMIHOSTING)
15 
16 #include <_ansi.h>
17 #include <_syslist.h>
18 #include <errno.h>
19 //#include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <sys/times.h>
23 #include <limits.h>
24 #include <signal.h>
25 
26 void
27 __initialize_args(int* p_argc, char*** p_argv);
28 
29 // This is the standard default implementation for the routine to
30 // process args. It returns a single empty arg.
31 // For semihosting applications, this is redefined to get the real
32 // args from the debugger. You can also use it if you decide to keep
33 // some args in a non-volatile memory.
34 
35 void __attribute__((weak))
36 __initialize_args(int* p_argc, char*** p_argv)
37 {
38  // By the time we reach this, the data and bss should have been initialised.
39 
40  // The strings pointed to by the argv array shall be modifiable by the
41  // program, and retain their last-stored values between program startup
42  // and program termination. (static, no const)
43  static char name[] = "";
44 
45  // The string pointed to by argv[0] represents the program name;
46  // argv[0][0] shall be the null character if the program name is not
47  // available from the host environment. argv[argc] shall be a null pointer.
48  // (static, no const)
49  static char* argv[2] =
50  { name, NULL };
51 
52  *p_argc = 1;
53  *p_argv = &argv[0];
54  return;
55 }
56 
57 // These functions are defined here to avoid linker errors in freestanding
58 // applications. They might be called in some error cases from library
59 // code.
60 //
61 // If you detect other functions to be needed, just let us know
62 // and we'll add them.
63 
64 int
65 raise(int sig __attribute__((unused)))
66 {
67  errno = ENOSYS;
68  return -1;
69 }
70 
71 int
72 kill(pid_t pid, int sig);
73 
74 int
75 kill(pid_t pid __attribute__((unused)), int sig __attribute__((unused)))
76 {
77  errno = ENOSYS;
78  return -1;
79 }
80 
81 #endif // !defined(OS_USE_SEMIHOSTING)
82 
83 // ----------------------------------------------------------------------------
84 
85 // If you need the empty definitions, remove the -ffreestanding option.
86 
87 #if __STDC_HOSTED__ == 1
88 
89 char* __env[1] =
90 { 0 };
91 char** environ = __env;
92 
93 #if !defined(OS_USE_SEMIHOSTING)
94 
95 // Forward declarations
96 
97 int
98 _chown(const char* path, uid_t owner, gid_t group);
99 
100 int
101 _close(int fildes);
102 
103 int
104 _execve(char* name, char** argv, char** env);
105 
106 int
107 _fork(void);
108 
109 int
110 _fstat(int fildes, struct stat* st);
111 
112 int
113 _getpid(void);
114 
115 int
116 _gettimeofday(struct timeval* ptimeval, void* ptimezone);
117 
118 int
119 _isatty(int file);
120 
121 int
122 _kill(int pid, int sig);
123 
124 int
125 _link(char* existing, char* _new);
126 
127 int
128 _lseek(int file, int ptr, int dir);
129 
130 int
131 _open(char* file, int flags, int mode);
132 
133 int
134 _read(int file, char* ptr, int len);
135 
136 int
137 _readlink(const char* path, char* buf, size_t bufsize);
138 
139 int
140 _stat(const char* file, struct stat* st);
141 
142 int
143 _symlink(const char* path1, const char* path2);
144 
145 clock_t
146 _times(struct tms* buf);
147 
148 int
149 _unlink(char* name);
150 
151 int
152 _wait(int* status);
153 
154 int
155 _write(int file, char* ptr, int len);
156 
157 // Definitions
158 
159 int __attribute__((weak))
160 _chown(const char* path __attribute__((unused)),
161  uid_t owner __attribute__((unused)), gid_t group __attribute__((unused)))
162 {
163  errno = ENOSYS;
164  return -1;
165 }
166 
167 int __attribute__((weak))
168 _close(int fildes __attribute__((unused)))
169 {
170  errno = ENOSYS;
171  return -1;
172 }
173 
174 int __attribute__((weak))
175 _execve(char* name __attribute__((unused)), char** argv __attribute__((unused)),
176  char** env __attribute__((unused)))
177 {
178  errno = ENOSYS;
179  return -1;
180 }
181 
182 int __attribute__((weak))
183 _fork(void)
184 {
185  errno = ENOSYS;
186  return -1;
187 }
188 
189 int __attribute__((weak))
190 _fstat(int fildes __attribute__((unused)),
191  struct stat* st __attribute__((unused)))
192 {
193  errno = ENOSYS;
194  return -1;
195 }
196 
197 int __attribute__((weak))
198 _getpid(void)
199 {
200  errno = ENOSYS;
201  return -1;
202 }
203 
204 int __attribute__((weak))
205 _gettimeofday(struct timeval* ptimeval __attribute__((unused)),
206  void* ptimezone __attribute__((unused)))
207 {
208  errno = ENOSYS;
209  return -1;
210 }
211 
212 int __attribute__((weak))
213 _isatty(int file __attribute__((unused)))
214 {
215  errno = ENOSYS;
216  return 0;
217 }
218 
219 int __attribute__((weak))
220 _kill(int pid __attribute__((unused)), int sig __attribute__((unused)))
221 {
222  errno = ENOSYS;
223  return -1;
224 }
225 
226 int __attribute__((weak))
227 _link(char* existing __attribute__((unused)),
228  char* _new __attribute__((unused)))
229 {
230  errno = ENOSYS;
231  return -1;
232 }
233 
234 int __attribute__((weak))
235 _lseek(int file __attribute__((unused)), int ptr __attribute__((unused)),
236  int dir __attribute__((unused)))
237 {
238  errno = ENOSYS;
239  return -1;
240 }
241 
242 int __attribute__((weak))
243 _open(char* file __attribute__((unused)), int flags __attribute__((unused)),
244  int mode __attribute__((unused)))
245 {
246  errno = ENOSYS;
247  return -1;
248 }
249 
250 int __attribute__((weak))
251 _read(int file __attribute__((unused)), char* ptr __attribute__((unused)),
252  int len __attribute__((unused)))
253 {
254  errno = ENOSYS;
255  return -1;
256 }
257 
258 int __attribute__((weak))
259 _readlink(const char* path __attribute__((unused)),
260  char* buf __attribute__((unused)), size_t bufsize __attribute__((unused)))
261 {
262  errno = ENOSYS;
263  return -1;
264 }
265 
266 int __attribute__((weak))
267 _stat(const char* file __attribute__((unused)),
268  struct stat* st __attribute__((unused)))
269 {
270  errno = ENOSYS;
271  return -1;
272 }
273 
274 int __attribute__((weak))
275 _symlink(const char* path1 __attribute__((unused)),
276  const char* path2 __attribute__((unused)))
277 {
278  errno = ENOSYS;
279  return -1;
280 }
281 
282 clock_t __attribute__((weak))
283 _times(struct tms* buf __attribute__((unused)))
284 {
285  errno = ENOSYS;
286  return ((clock_t) -1);
287 }
288 
289 int __attribute__((weak))
290 _unlink(char* name __attribute__((unused)))
291 {
292  errno = ENOSYS;
293  return -1;
294 }
295 
296 int __attribute__((weak))
297 _wait(int* status __attribute__((unused)))
298 {
299  errno = ENOSYS;
300  return -1;
301 }
302 
303 int __attribute__((weak))
304 _write(int file __attribute__((unused)), char* ptr __attribute__((unused)),
305  int len __attribute__((unused)))
306 {
307  errno = ENOSYS;
308  return -1;
309 }
310 
311 // ----------------------------------------------------------------------------
312 
313 #else // defined(OS_USE_SEMIHOSTING)
314 
315 // ----------------------------------------------------------------------------
316 
317 /* Support files for GNU libc. Files in the system namespace go here.
318  Files in the C namespace (ie those that do not start with an
319  underscore) go in .c. */
320 
321 #include <_ansi.h>
322 #include <stdint.h>
323 //#include <sys/types.h>
324 #include <sys/stat.h>
325 #include <sys/fcntl.h>
326 #include <stdio.h>
327 #include <string.h>
328 #include <time.h>
329 #include <sys/time.h>
330 #include <sys/times.h>
331 #include <errno.h>
332 #include <reent.h>
333 #include <unistd.h>
334 #include <sys/wait.h>
335 #include <ctype.h>
336 #include <signal.h>
337 
338 #include "semihosting.h"
339 
340 int _kill (int pid, int sig);
341 
342 void __attribute__((noreturn)) _exit (int status);
343 
344 // Forward declarations.
345 int _system (const char*);
346 int _rename (const char*, const char*);
347 int _isatty (int);
348 clock_t _times (struct tms*);
349 int _gettimeofday (struct timeval *, void*);
350 int _unlink (const char*);
351 int _link (void);
352 
353 int _stat (const char*, struct stat*);
354 
355 int _fstat (int, struct stat*);
356 int _swistat (int fd, struct stat* st);
357 int _getpid (int);
358 int _close (int);
359 clock_t _clock (void);
360 int _swiclose (int);
361 int _open (const char*, int, ...);
362 int _swiopen (const char*, int);
363 int _write (int, char*, int);
364 int _swiwrite (int, char*, int);
365 int _lseek (int, int, int);
366 int _swilseek (int, int, int);
367 int _read (int, char*, int);
368 int _swiread (int, char*, int);
369 
370 void initialise_monitor_handles (void);
371 
372 void __initialize_args (int* p_argc, char*** p_argv);
373 
374 static int
375 checkerror (int);
376 static int
377 error (int);
378 static int
379 get_errno (void);
380 
381 // ----------------------------------------------------------------------------
382 
383 #define ARGS_BUF_ARRAY_SIZE 80
384 #define ARGV_BUF_ARRAY_SIZE 10
385 
386 typedef struct
387 {
388  char* pCommandLine;
389  int size;
390 } CommandLineBlock;
391 
392 void __initialize_args (int* p_argc, char*** p_argv)
393 {
394  // Array of chars to receive the command line from the host
395  static char args_buf[ARGS_BUF_ARRAY_SIZE];
396 
397  // Array of pointers to store the final argv pointers (pointing
398  // in the above array).
399  static char* argv_buf[ARGV_BUF_ARRAY_SIZE];
400 
401  int argc = 0;
402  int isInArgument = 0;
403 
404  CommandLineBlock cmdBlock;
405  cmdBlock.pCommandLine = args_buf;
406  cmdBlock.size = sizeof(args_buf) - 1;
407 
408  int ret = call_host (SEMIHOSTING_SYS_GET_CMDLINE, &cmdBlock);
409  if (ret == 0)
410  {
411 
412  // In case the host send more than we can chew, limit the
413  // string to our buffer.
414  args_buf[ARGS_BUF_ARRAY_SIZE - 1] = '\0';
415 
416  // The command line is a null terminated string
417  char* p = cmdBlock.pCommandLine;
418 
419  int delim = '\0';
420  int ch;
421 
422  while ((ch = *p) != '\0')
423  {
424  if (isInArgument == 0)
425  {
426  if (!isblank(ch))
427  {
428  if (argc >= (int) ((sizeof(argv_buf) / sizeof(argv_buf[0])) - 1))
429  break;
430 
431  if (ch == '"' || ch == '\'')
432  {
433  // Remember the delimiter to search for the
434  // corresponding terminator
435  delim = ch;
436  ++p; // skip the delimiter
437  ch = *p;
438  }
439  // Remember the arg beginning address
440  argv_buf[argc++] = p;
441  isInArgument = 1;
442  }
443  }
444  else if (delim != '\0')
445  {
446  if ((ch == delim))
447  {
448  delim = '\0';
449  *p = '\0';
450  isInArgument = 0;
451  }
452  }
453  else if (isblank(ch))
454  {
455  delim = '\0';
456  *p = '\0';
457  isInArgument = 0;
458  }
459  ++p;
460  }
461  }
462 
463  if (argc == 0)
464  {
465  // No args found in string, return a single empty name.
466  args_buf[0] = '\0';
467  argv_buf[0] = &args_buf[0];
468  ++argc;
469  }
470 
471  // Must end the array with a null pointer.
472  argv_buf[argc] = NULL;
473 
474  *p_argc = argc;
475  *p_argv = &argv_buf[0];
476 
477  // temporary here
478  initialise_monitor_handles ();
479 
480  return;
481 }
482 
483 // ----------------------------------------------------------------------------
484 
485 void _exit (int status)
486 {
487  /* There is only one SWI for both _exit and _kill. For _exit, call
488  the SWI with the second argument set to -1, an invalid value for
489  signum, so that the SWI handler can distinguish the two calls.
490  Note: The RDI implementation of _kill throws away both its
491  arguments. */
492  report_exception (status == 0 ? ADP_Stopped_ApplicationExit : ADP_Stopped_RunTimeError);
493 }
494 
495 // ----------------------------------------------------------------------------
496 
497 int __attribute__((weak))
498 _kill (int pid __attribute__((unused)), int sig __attribute__((unused)))
499 {
500  errno = ENOSYS;
501  return -1;
502 }
503 
504 // ----------------------------------------------------------------------------
505 
506 /* Struct used to keep track of the file position, just so we
507  can implement fseek(fh,x,SEEK_CUR). */
508 struct fdent
509 {
510  int handle;
511  int pos;
512 };
513 
514 #define MAX_OPEN_FILES 20
515 
516 /* User file descriptors (fd) are integer indexes into
517  the openfiles[] array. Error checking is done by using
518  findslot().
519 
520  This openfiles array is manipulated directly by only
521  these 5 functions:
522 
523  findslot() - Translate entry.
524  newslot() - Find empty entry.
525  initilise_monitor_handles() - Initialize entries.
526  _swiopen() - Initialize entry.
527  _close() - Handle stdout == stderr case.
528 
529  Every other function must use findslot(). */
530 
531 static struct fdent openfiles[MAX_OPEN_FILES];
532 
533 static struct fdent* findslot (int);
534 static int newslot (void);
535 
536 /* Register name faking - works in collusion with the linker. */
537 register char* stack_ptr asm ("sp");
538 
539 /* following is copied from libc/stdio/local.h to check std streams */
540 extern void __sinit(struct _reent*);
541 #define CHECK_INIT(ptr) \
542  do \
543  { \
544  if ((ptr) && !(ptr)->__sdidinit) \
545  __sinit (ptr); \
546  } \
547  while (0)
548 
549 static int monitor_stdin;
550 static int monitor_stdout;
551 static int monitor_stderr;
552 
553 /* Return a pointer to the structure associated with
554  the user file descriptor fd. */
555 static struct fdent*
556 findslot (int fd)
557 {
558  CHECK_INIT(_REENT);
559 
560  /* User file descriptor is out of range. */
561  if ((unsigned int) fd >= MAX_OPEN_FILES)
562  {
563  return NULL;
564  }
565 
566  /* User file descriptor is open? */
567  if (openfiles[fd].handle == -1)
568  {
569  return NULL;
570  }
571 
572  /* Valid. */
573  return &openfiles[fd];
574 }
575 
576 /* Return the next lowest numbered free file
577  structure, or -1 if we can't find one. */
578 static int
579 newslot (void)
580 {
581  int i;
582 
583  for (i = 0; i < MAX_OPEN_FILES; i++)
584  {
585  if (openfiles[i].handle == -1)
586  {
587  break;
588  }
589  }
590 
591  if (i == MAX_OPEN_FILES)
592  {
593  return -1;
594  }
595 
596  return i;
597 }
598 
599 void
600 initialise_monitor_handles (void)
601 {
602  int i;
603 
604  /* Open the standard file descriptors by opening the special
605  * teletype device, ":tt", read-only to obtain a descriptor for
606  * standard input and write-only to obtain a descriptor for standard
607  * output. Finally, open ":tt" in append mode to obtain a descriptor
608  * for standard error. Since this is a write mode, most kernels will
609  * probably return the same value as for standard output, but the
610  * kernel can differentiate the two using the mode flag and return a
611  * different descriptor for standard error.
612  */
613 
614  int volatile block[3];
615 
616  block[0] = (int) ":tt";
617  block[2] = 3; /* length of filename */
618  block[1] = 0; /* mode "r" */
619  monitor_stdin = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
620 
621  block[0] = (int) ":tt";
622  block[2] = 3; /* length of filename */
623  block[1] = 4; /* mode "w" */
624  monitor_stdout = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
625 
626  block[0] = (int) ":tt";
627  block[2] = 3; /* length of filename */
628  block[1] = 8; /* mode "a" */
629  monitor_stderr = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
630 
631  /* If we failed to open stderr, redirect to stdout. */
632  if (monitor_stderr == -1)
633  {
634  monitor_stderr = monitor_stdout;
635  }
636 
637  for (i = 0; i < MAX_OPEN_FILES; i++)
638  {
639  openfiles[i].handle = -1;
640  }
641 
642  openfiles[0].handle = monitor_stdin;
643  openfiles[0].pos = 0;
644  openfiles[1].handle = monitor_stdout;
645  openfiles[1].pos = 0;
646  openfiles[2].handle = monitor_stderr;
647  openfiles[2].pos = 0;
648 }
649 
650 static int
651 get_errno (void)
652 {
653  return call_host (SEMIHOSTING_SYS_ERRNO, NULL);
654 }
655 
656 /* Set errno and return result. */
657 static int
658 error (int result)
659 {
660  errno = get_errno ();
661  return result;
662 }
663 
664 /* Check the return and set errno appropriately. */
665 static int
666 checkerror (int result)
667 {
668  if (result == -1)
669  {
670  return error (-1);
671  }
672 
673  return result;
674 }
675 
676 /* fh, is a valid internal file handle.
677  ptr, is a null terminated string.
678  len, is the length in bytes to read.
679  Returns the number of bytes *not* written. */
680 int
681 _swiread (int fh, char* ptr, int len)
682 {
683  int block[3];
684 
685  block[0] = fh;
686  block[1] = (int) ptr;
687  block[2] = len;
688 
689  return checkerror (call_host (SEMIHOSTING_SYS_READ, block));
690 }
691 
692 /* fd, is a valid user file handle.
693  Translates the return of _swiread into
694  bytes read. */
695 int
696 _read (int fd, char* ptr, int len)
697 {
698  int res;
699  struct fdent *pfd;
700 
701  pfd = findslot (fd);
702  if (pfd == NULL)
703  {
704  errno = EBADF;
705  return -1;
706  }
707 
708  res = _swiread (pfd->handle, ptr, len);
709 
710  if (res == -1)
711  {
712  return res;
713  }
714 
715  pfd->pos += len - res;
716 
717  /* res == len is not an error,
718  at least if we want feof() to work. */
719  return len - res;
720 }
721 
722 /* fd, is a user file descriptor. */
723 int _swilseek (int fd, int ptr, int dir)
724 {
725  int res;
726  struct fdent *pfd;
727 
728  /* Valid file descriptor? */
729  pfd = findslot (fd);
730  if (pfd == NULL)
731  {
732  errno = EBADF;
733  return -1;
734  }
735 
736  /* Valid whence? */
737  if ((dir != SEEK_CUR) && (dir != SEEK_SET) && (dir != SEEK_END))
738  {
739  errno = EINVAL;
740  return -1;
741  }
742 
743  /* Convert SEEK_CUR to SEEK_SET */
744  if (dir == SEEK_CUR)
745  {
746  ptr = pfd->pos + ptr;
747  /* The resulting file offset would be negative. */
748  if (ptr < 0)
749  {
750  errno = EINVAL;
751  if ((pfd->pos > 0) && (ptr > 0))
752  {
753  errno = EOVERFLOW;
754  }
755  return -1;
756  }
757  dir = SEEK_SET;
758  }
759 
760  int block[2];
761  if (dir == SEEK_END)
762  {
763  block[0] = pfd->handle;
764  res = checkerror (call_host (SEMIHOSTING_SYS_FLEN, block));
765  if (res == -1)
766  {
767  return -1;
768  }
769  ptr += res;
770  }
771 
772  /* This code only does absolute seeks. */
773  block[0] = pfd->handle;
774  block[1] = ptr;
775  res = checkerror (call_host (SEMIHOSTING_SYS_SEEK, block));
776 
777  /* At this point ptr is the current file position. */
778  if (res >= 0)
779  {
780  pfd->pos = ptr;
781  return ptr;
782  }
783  else
784  {
785  return -1;
786  }
787 }
788 
789 int _lseek (int fd, int ptr, int dir)
790 {
791  return _swilseek (fd, ptr, dir);
792 }
793 
794 /* fh, is a valid internal file handle.
795  Returns the number of bytes *not* written. */
796 int _swiwrite (int fh, char* ptr, int len)
797 {
798  int block[3];
799 
800  block[0] = fh;
801  block[1] = (int) ptr;
802  block[2] = len;
803 
804  return checkerror (call_host (SEMIHOSTING_SYS_WRITE, block));
805 }
806 
807 /* fd, is a user file descriptor. */
808 int _write (int fd, char* ptr, int len)
809 {
810  int res;
811  struct fdent *pfd;
812 
813  pfd = findslot (fd);
814  if (pfd == NULL)
815  {
816  errno = EBADF;
817  return -1;
818  }
819 
820  res = _swiwrite (pfd->handle, ptr, len);
821 
822  /* Clearly an error. */
823  if (res < 0)
824  {
825  return -1;
826  }
827 
828  pfd->pos += len - res;
829 
830  /* We wrote 0 bytes?
831  Retrieve errno just in case. */
832  if ((len - res) == 0)
833  {
834  return error (0);
835  }
836 
837  return (len - res);
838 }
839 
840 int _swiopen (const char* path, int flags)
841 {
842  int aflags = 0, fh;
843  uint32_t block[3];
844 
845  int fd = newslot ();
846 
847  if (fd == -1)
848  {
849  errno = EMFILE;
850  return -1;
851  }
852 
853  /* It is an error to open a file that already exists. */
854  if ((flags & O_CREAT) && (flags & O_EXCL))
855  {
856  struct stat st;
857  int res;
858  res = _stat (path, &st);
859  if (res != -1)
860  {
861  errno = EEXIST;
862  return -1;
863  }
864  }
865 
866  /* The flags are Unix-style, so we need to convert them. */
867 #ifdef O_BINARY
868  if (flags & O_BINARY)
869  {
870  aflags |= 1;
871  }
872 #endif
873 
874  /* In O_RDONLY we expect aflags == 0. */
875 
876  if (flags & O_RDWR)
877  {
878  aflags |= 2;
879  }
880 
881  if ((flags & O_CREAT) || (flags & O_TRUNC) || (flags & O_WRONLY))
882  {
883  aflags |= 4;
884  }
885 
886  if (flags & O_APPEND)
887  {
888  /* Can't ask for w AND a; means just 'a'. */
889  aflags &= ~4;
890  aflags |= 8;
891  }
892 
893  block[0] = (uint32_t) path;
894  block[2] = strlen (path);
895  block[1] = (uint32_t) aflags;
896 
897  fh = call_host (SEMIHOSTING_SYS_OPEN, block);
898 
899  /* Return a user file descriptor or an error. */
900  if (fh >= 0)
901  {
902  openfiles[fd].handle = fh;
903  openfiles[fd].pos = 0;
904  return fd;
905  }
906  else
907  {
908  return error (fh);
909  }
910 }
911 
912 int _open (const char* path, int flags, ...)
913 {
914  return _swiopen (path, flags);
915 }
916 
917 /* fh, is a valid internal file handle. */
918 int _swiclose (int fh)
919 {
920  return checkerror (call_host (SEMIHOSTING_SYS_CLOSE, &fh));
921 }
922 
923 /* fd, is a user file descriptor. */
924 int _close (int fd)
925 {
926  int res;
927  struct fdent *pfd;
928 
929  pfd = findslot (fd);
930  if (pfd == NULL)
931  {
932  errno = EBADF;
933  return -1;
934  }
935 
936  /* Handle stderr == stdout. */
937  if ((fd == 1 || fd == 2) && (openfiles[1].handle == openfiles[2].handle))
938  {
939  pfd->handle = -1;
940  return 0;
941  }
942 
943  /* Attempt to close the handle. */
944  res = _swiclose (pfd->handle);
945 
946  /* Reclaim handle? */
947  if (res == 0)
948  {
949  pfd->handle = -1;
950  }
951 
952  return res;
953 }
954 
955 int __attribute__((weak))
956 _getpid (int n __attribute__ ((unused)))
957 {
958  return 1;
959 }
960 
961 int
962 _swistat (int fd, struct stat* st)
963 {
964  struct fdent *pfd;
965  int res;
966 
967  pfd = findslot (fd);
968  if (pfd == NULL)
969  {
970  errno = EBADF;
971  return -1;
972  }
973 
974  /* Always assume a character device,
975  with 1024 byte blocks. */
976  st->st_mode |= S_IFCHR;
977  st->st_blksize = 1024;
978  res = checkerror (call_host (SEMIHOSTING_SYS_FLEN, &pfd->handle));
979  if (res == -1)
980  {
981  return -1;
982  }
983 
984  /* Return the file size. */
985  st->st_size = res;
986  return 0;
987 }
988 
989 int __attribute__((weak))
990 _fstat (int fd, struct stat* st)
991 {
992  memset (st, 0, sizeof(*st));
993  return _swistat (fd, st);
994 }
995 
996 int __attribute__((weak))
997 _stat (const char*fname, struct stat *st)
998 {
999  int fd, res;
1000  memset (st, 0, sizeof(*st));
1001  /* The best we can do is try to open the file readonly.
1002  If it exists, then we can guess a few things about it. */
1003  if ((fd = _open (fname, O_RDONLY)) == -1)
1004  {
1005  return -1;
1006  }
1007  st->st_mode |= S_IFREG | S_IREAD;
1008  res = _swistat (fd, st);
1009  /* Not interested in the error. */
1010  _close (fd);
1011  return res;
1012 }
1013 
1014 int __attribute__((weak))
1015 _link (void)
1016 {
1017  errno = ENOSYS;
1018  return -1;
1019 }
1020 
1021 int _unlink (const char* path)
1022 {
1023  int res;
1024  uint32_t block[2];
1025  block[0] = (uint32_t) path;
1026  block[1] = strlen (path);
1027  res = call_host (SEMIHOSTING_SYS_REMOVE, block);
1028 
1029  if (res == -1)
1030  {
1031  return error (res);
1032  }
1033  return 0;
1034 }
1035 
1036 int _gettimeofday (struct timeval* tp, void* tzvp)
1037 {
1038  struct timezone* tzp = tzvp;
1039  if (tp)
1040  {
1041  /* Ask the host for the seconds since the Unix epoch. */
1042  tp->tv_sec = call_host (SEMIHOSTING_SYS_TIME, NULL);
1043  tp->tv_usec = 0;
1044  }
1045 
1046  /* Return fixed data for the timezone. */
1047  if (tzp)
1048  {
1049  tzp->tz_minuteswest = 0;
1050  tzp->tz_dsttime = 0;
1051  }
1052 
1053  return 0;
1054 }
1055 
1056 /* Return a clock that ticks at 100Hz. */
1057 clock_t _clock (void)
1058 {
1059  clock_t timeval;
1060 
1061  timeval = (clock_t) call_host (SEMIHOSTING_SYS_CLOCK, NULL);
1062  return timeval;
1063 }
1064 
1065 /* Return a clock that ticks at 100Hz. */
1066 clock_t
1067 _times (struct tms* tp)
1068 {
1069  clock_t timeval = _clock ();
1070 
1071  if (tp)
1072  {
1073  tp->tms_utime = timeval; /* user time */
1074  tp->tms_stime = 0; /* system time */
1075  tp->tms_cutime = 0; /* user time, children */
1076  tp->tms_cstime = 0; /* system time, children */
1077  }
1078 
1079  return timeval;
1080 }
1081 
1082 int _isatty (int fd)
1083 {
1084  struct fdent *pfd;
1085  int tty;
1086 
1087  pfd = findslot (fd);
1088  if (pfd == NULL)
1089  {
1090  errno = EBADF;
1091  return 0;
1092  }
1093 
1094  tty = call_host (SEMIHOSTING_SYS_ISTTY, &pfd->handle);
1095 
1096  if (tty == 1)
1097  {
1098  return 1;
1099  }
1100 
1101  errno = get_errno ();
1102  return 0;
1103 }
1104 
1105 int _system (const char* s)
1106 {
1107  uint32_t block[2];
1108  int e;
1109 
1110  /* Hmmm. The ARM debug interface specification doesn't say whether
1111  SYS_SYSTEM does the right thing with a null argument, or assign any
1112  meaning to its return value. Try to do something reasonable.... */
1113  if (!s)
1114  {
1115  return 1; /* maybe there is a shell available? we can hope. :-P */
1116  }
1117  block[0] = (uint32_t) s;
1118  block[1] = strlen (s);
1119  e = checkerror (call_host (SEMIHOSTING_SYS_SYSTEM, block));
1120  if ((e >= 0) && (e < 256))
1121  {
1122  /* We have to convert e, an exit status to the encoded status of
1123  the command. To avoid hard coding the exit status, we simply
1124  loop until we find the right position. */
1125  int exit_code;
1126 
1127  for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
1128  {
1129  continue;
1130  }
1131  }
1132  return e;
1133 }
1134 
1135 int _rename (const char* oldpath, const char* newpath)
1136 {
1137  uint32_t block[4];
1138  block[0] = (uint32_t) oldpath;
1139  block[1] = strlen (oldpath);
1140  block[2] = (uint32_t) newpath;
1141  block[3] = strlen (newpath);
1142  return checkerror (call_host (SEMIHOSTING_SYS_RENAME, block)) ? -1 : 0;
1143 }
1144 
1145 // ----------------------------------------------------------------------------
1146 // Required by Google Tests
1147 
1148 int mkdir (const char *path __attribute__((unused)), mode_t mode __attribute__((unused)))
1149 {
1150 #if 0
1151  // always return true
1152  return 0;
1153 #else
1154  errno = ENOSYS;
1155  return -1;
1156 #endif
1157 }
1158 
1159 char *getcwd (char *buf, size_t size)
1160 {
1161  // no cwd available via semihosting, so we use the temporary folder
1162  strncpy (buf, "/tmp", size);
1163  return buf;
1164 }
1165 
1166 #endif // defined OS_USE_SEMIHOSTING
1167 
1168 #endif // __STDC_HOSTED__ == 1
void __initialize_args(int *p_argc, char ***p_argv)
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
#define NULL
NULL pointer.
int errno
Definition: _syscalls.c:9
int kill(pid_t pid, int sig)