OpenOCD
semihosting_common.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2018 by Liviu Ionescu *
5  * <ilg@livius.net> *
6  * *
7  * Copyright (C) 2018 by Marvell Technology Group Ltd. *
8  * Written by Nicolas Pitre <nico@marvell.com> *
9  * *
10  * Copyright (C) 2010 by Spencer Oliver *
11  * spen@spen-soft.co.uk *
12  * *
13  * Copyright (C) 2016 by Square, Inc. *
14  * Steven Stallion <stallion@squareup.com> *
15  ***************************************************************************/
16 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include "target.h"
37 #include "target_type.h"
38 #include "semihosting_common.h"
39 
40 #include <helper/binarybuffer.h>
41 #include <helper/log.h>
42 #include <server/gdb_server.h>
43 #include <sys/stat.h>
44 
50 enum {
51  TARGET_O_RDONLY = 0x000,
52  TARGET_O_WRONLY = 0x001,
53  TARGET_O_RDWR = 0x002,
54  TARGET_O_APPEND = 0x008,
55  TARGET_O_CREAT = 0x200,
56  TARGET_O_TRUNC = 0x400,
57  /* O_EXCL=0x800 is not required in this implementation. */
58 };
59 
60 /* GDB remote protocol does not differentiate between text and binary open modes. */
61 static const int open_gdb_modeflags[12] = {
74 };
75 
76 static const int open_host_modeflags[12] = {
77  O_RDONLY,
78  O_RDONLY | O_BINARY,
79  O_RDWR,
80  O_RDWR | O_BINARY,
81  O_WRONLY | O_CREAT | O_TRUNC,
82  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
83  O_RDWR | O_CREAT | O_TRUNC,
84  O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
85  O_WRONLY | O_CREAT | O_APPEND,
86  O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
87  O_RDWR | O_CREAT | O_APPEND,
88  O_RDWR | O_CREAT | O_APPEND | O_BINARY
89 };
90 
92  struct gdb_fileio_info *fileio_info);
93 static int semihosting_common_fileio_end(struct target *target, int result,
94  int fileio_errno, bool ctrl_c);
95 static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields);
96 static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields);
97 
106 int semihosting_common_init(struct target *target, void *setup,
107  void *post_result)
108 {
109  LOG_DEBUG(" ");
110 
111  target->fileio_info = malloc(sizeof(*target->fileio_info));
112  if (!target->fileio_info) {
113  LOG_ERROR("out of memory");
114  return ERROR_FAIL;
115  }
116  memset(target->fileio_info, 0, sizeof(*target->fileio_info));
117 
118  struct semihosting *semihosting;
119  semihosting = malloc(sizeof(*target->semihosting));
120  if (!semihosting) {
121  LOG_ERROR("out of memory");
122  return ERROR_FAIL;
123  }
124 
125  semihosting->is_active = false;
128  semihosting->stdin_fd = -1;
129  semihosting->stdout_fd = -1;
130  semihosting->stderr_fd = -1;
131  semihosting->is_fileio = false;
132  semihosting->hit_fileio = false;
133  semihosting->is_resumable = false;
136  semihosting->op = -1;
137  semihosting->param = 0;
138  semihosting->result = -1;
139  semihosting->sys_errno = -1;
142 
143  /* If possible, update it in setup(). */
144  semihosting->setup_time = clock();
145 
149 
151 
154 
155  return ERROR_OK;
156 }
157 
160  char *name;
161  int error;
162 };
163 
165 {
167  return false;
168 
169  bool is_read_op = false;
170 
171  switch (semihosting->op) {
172  /* check debug semihosting operations: READC, WRITEC and WRITE0 */
174  is_read_op = true;
175  /* fall through */
178  /* debug operations are redirected when CFG is either DEBUG or ALL */
180  return false;
181  break;
182 
183  /* check stdio semihosting operations: READ and WRITE */
185  is_read_op = true;
186  /* fall through */
188  /* stdio operations are redirected when CFG is either STDIO or ALL */
190  return false;
191  break;
192 
193  default:
194  return false;
195  }
196 
197  if (is_read_op)
198  return fd == semihosting->stdin_fd;
199 
200  /* write operation */
201  return fd == semihosting->stdout_fd || fd == semihosting->stderr_fd;
202 }
203 
204 static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size)
205 {
206  if (!semihosting->tcp_connection) {
207  LOG_ERROR("No connected TCP client for semihosting");
208  semihosting->sys_errno = EBADF; /* Bad file number */
209  return -1;
210  }
211 
213 
214  int retval = connection_write(semihosting->tcp_connection, buf, size);
215 
216  if (retval < 0)
218 
219  return retval;
220 }
221 
222 static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size)
223 {
226 
227  /* default write */
228  int result = write(fd, buf, size);
229  if (result == -1)
230  semihosting->sys_errno = errno;
231  return result;
232 }
233 
234 static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
235 {
236  if (!semihosting->tcp_connection) {
237  LOG_ERROR("No connected TCP client for semihosting");
238  semihosting->sys_errno = EBADF; /* Bad file number */
239  return -1;
240  }
241 
243 
244  service->error = ERROR_OK;
246 
247  int retval = connection_read(semihosting->tcp_connection, buf, size);
248 
249  if (retval <= 0)
251 
252  if (retval < 0)
254 
256 
257  return retval;
258 }
259 
260 static inline int semihosting_putchar(struct semihosting *semihosting, int fd, int c)
261 {
264 
265  /* default putchar */
266  return putchar(c);
267 }
268 
269 static inline ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size)
270 {
273 
274  /* default read */
275  ssize_t result = read(fd, buf, size);
276  if (result == -1)
277  semihosting->sys_errno = errno;
278 
279  return result;
280 }
281 
282 static inline int semihosting_getchar(struct semihosting *semihosting, int fd)
283 {
285  unsigned char c;
286 
287  if (semihosting_redirect_read(semihosting, &c, 1) > 0)
288  return c;
289 
290  return EOF;
291  }
292 
293  /* default getchar */
294  return getchar();
295 }
296 
302 
308 static const char *semihosting_opcode_to_str(const uint64_t opcode)
309 {
310  switch (opcode) {
312  return "CLOSE";
314  return "CLOCK";
316  return "ELAPSED";
318  return "ERRNO";
320  return "EXIT";
322  return "EXIT_EXTENDED";
324  return "FLEN";
326  return "GET_CMDLINE";
328  return "HEAPINFO";
330  return "ISERROR";
332  return "ISTTY";
334  return "OPEN";
336  return "READ";
338  return "READC";
340  return "REMOVE";
342  return "RENAME";
344  return "SEEK";
346  return "SYSTEM";
348  return "TICKFREQ";
350  return "TIME";
352  return "TMPNAM";
354  return "WRITE";
356  return "WRITEC";
358  return "WRITE0";
360  return "USER_CMD";
362  return "ARM_RESERVED_CMD";
363  default:
364  return "<unknown>";
365  }
366 }
367 
374 {
376  if (!semihosting) {
377  /* Silently ignore if the semihosting field was not set. */
378  return ERROR_OK;
379  }
380 
381  struct gdb_fileio_info *fileio_info = target->fileio_info;
382 
383  /*
384  * By default return an error.
385  * The actual result must be set by each function
386  */
387  semihosting->result = -1;
388 
389  /* Most operations are resumable, except the two exit calls. */
390  semihosting->is_resumable = true;
391 
392  int retval;
393 
394  /* Enough space to hold 4 long words. */
395  uint8_t fields[4*8];
396 
397  LOG_DEBUG("op=0x%x (%s), param=0x%" PRIx64, semihosting->op,
399  semihosting->param);
400 
401  switch (semihosting->op) {
402  case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
403  /*
404  * Returns the number of centiseconds (hundredths of a second)
405  * since the execution started.
406  *
407  * Values returned can be of limited use for some benchmarking
408  * purposes because of communication overhead or other
409  * agent-specific factors. For example, with a debug hardware
410  * unit the request is passed back to the host for execution.
411  * This can lead to unpredictable delays in transmission and
412  * process scheduling.
413  *
414  * Use this function to calculate time intervals, by calculating
415  * differences between intervals with and without the code
416  * sequence to be timed.
417  *
418  * Entry
419  * The PARAMETER REGISTER must contain 0. There are no other
420  * parameters.
421  *
422  * Return
423  * On exit, the RETURN REGISTER contains:
424  * - The number of centiseconds since some arbitrary start
425  * point, if the call is successful.
426  * - –1 if the call is not successful. For example, because
427  * of a communications error.
428  */
429  {
430  clock_t delta = clock() - semihosting->setup_time;
431 
432  semihosting->result = delta / (CLOCKS_PER_SEC / 100);
433  }
434  break;
435 
436  case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
437  /*
438  * Closes a file on the host system. The handle must reference
439  * a file that was opened with SYS_OPEN.
440  *
441  * Entry
442  * On entry, the PARAMETER REGISTER contains a pointer to a
443  * one-field argument block:
444  * - field 1 Contains a handle for an open file.
445  *
446  * Return
447  * On exit, the RETURN REGISTER contains:
448  * - 0 if the call is successful
449  * - –1 if the call is not successful.
450  */
451  retval = semihosting_read_fields(target, 1, fields);
452  if (retval != ERROR_OK)
453  return retval;
454 
455  {
456  int fd = semihosting_get_field(target, 0, fields);
457  /* Do not allow to close OpenOCD's own standard streams */
458  if (fd == 0 || fd == 1 || fd == 2) {
459  LOG_DEBUG("ignoring semihosting attempt to close %s",
460  (fd == 0) ? "stdin" :
461  (fd == 1) ? "stdout" : "stderr");
462  /* Just pretend success */
463  semihosting->result = 0;
464  break;
465  }
466  /* Close the descriptor */
467  if (semihosting->is_fileio) {
468  semihosting->hit_fileio = true;
469  fileio_info->identifier = "close";
470  fileio_info->param_1 = fd;
471  } else {
472  semihosting->result = close(fd);
473  if (semihosting->result == -1)
474  semihosting->sys_errno = errno;
475  LOG_DEBUG("close(%d)=%" PRId64, fd, semihosting->result);
476  }
477  }
478  break;
479 
480  case SEMIHOSTING_SYS_ERRNO: /* 0x13 */
481  /*
482  * Returns the value of the C library errno variable that is
483  * associated with the semihosting implementation. The errno
484  * variable can be set by a number of C library semihosted
485  * functions, including:
486  * - SYS_REMOVE
487  * - SYS_OPEN
488  * - SYS_CLOSE
489  * - SYS_READ
490  * - SYS_WRITE
491  * - SYS_SEEK.
492  *
493  * Whether errno is set or not, and to what value, is entirely
494  * host-specific, except where the ISO C standard defines the
495  * behavior.
496  *
497  * Entry
498  * There are no parameters. The PARAMETER REGISTER must be 0.
499  *
500  * Return
501  * On exit, the RETURN REGISTER contains the value of the C
502  * library errno variable.
503  */
505  break;
506 
507  case SEMIHOSTING_SYS_EXIT: /* 0x18 */
508  /*
509  * Note: SYS_EXIT was called angel_SWIreason_ReportException in
510  * previous versions of the documentation.
511  *
512  * An application calls this operation to report an exception
513  * to the debugger directly. The most common use is to report
514  * that execution has completed, using ADP_Stopped_ApplicationExit.
515  *
516  * Note: This semihosting operation provides no means for 32-bit
517  * callers to indicate an application exit with a specified exit
518  * code. Semihosting callers may prefer to check for the presence
519  * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
520  * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
521  * is available.
522  *
523  * Entry (32-bit)
524  * On entry, the PARAMETER register is set to a reason code
525  * describing the cause of the trap. Not all semihosting client
526  * implementations will necessarily trap every corresponding
527  * event. Important reason codes are:
528  *
529  * - ADP_Stopped_ApplicationExit 0x20026
530  * - ADP_Stopped_RunTimeErrorUnknown 0x20023
531  *
532  * Entry (64-bit)
533  * On entry, the PARAMETER REGISTER contains a pointer to a
534  * two-field argument block:
535  * - field 1 The exception type, which is one of the set of
536  * reason codes in the above tables.
537  * - field 2 A subcode, whose meaning depends on the reason
538  * code in field 1.
539  * In particular, if field 1 is ADP_Stopped_ApplicationExit
540  * then field 2 is an exit status code, as passed to the C
541  * standard library exit() function. A simulator receiving
542  * this request must notify a connected debugger, if present,
543  * and then exit with the specified status.
544  *
545  * Return
546  * No return is expected from these calls. However, it is
547  * possible for the debugger to request that the application
548  * continues by performing an RDI_Execute request or equivalent.
549  * In this case, execution continues with the registers as they
550  * were on entry to the operation, or as subsequently modified
551  * by the debugger.
552  */
553  if (semihosting->word_size_bytes == 8) {
554  retval = semihosting_read_fields(target, 2, fields);
555  if (retval != ERROR_OK)
556  return retval;
557 
558  int type = semihosting_get_field(target, 0, fields);
559  int code = semihosting_get_field(target, 1, fields);
560 
563  exit(code);
564 
565  fprintf(stderr,
566  "semihosting: *** application exited with %d ***\n",
567  code);
568  } else {
569  fprintf(stderr,
570  "semihosting: application exception %#x\n", type);
571  }
572  } else {
575  exit(0);
576 
577  fprintf(stderr,
578  "semihosting: *** application exited normally ***\n");
580  /* Chosen more or less arbitrarily to have a nicer message,
581  * otherwise all other return the same exit code 1. */
583  exit(1);
584 
585  fprintf(stderr,
586  "semihosting: *** application exited with error ***\n");
587  } else {
589  exit(1);
590 
591  fprintf(stderr,
592  "semihosting: application exception %#x\n",
593  (unsigned int)semihosting->param);
594  }
595  }
597  semihosting->is_resumable = false;
599  }
600  break;
601 
602  case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
603  /*
604  * This operation is only supported if the semihosting extension
605  * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
606  * reported using feature byte 0, bit 0. If this extension is
607  * supported, then the implementation provides a means to
608  * report a normal exit with a nonzero exit status in both 32-bit
609  * and 64-bit semihosting APIs.
610  *
611  * The implementation must provide the semihosting call
612  * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
613  *
614  * SYS_EXIT_EXTENDED is used by an application to report an
615  * exception or exit to the debugger directly. The most common
616  * use is to report that execution has completed, using
617  * ADP_Stopped_ApplicationExit.
618  *
619  * Entry
620  * On entry, the PARAMETER REGISTER contains a pointer to a
621  * two-field argument block:
622  * - field 1 The exception type, which should be one of the set
623  * of reason codes that are documented for the SYS_EXIT
624  * (0x18) call. For example, ADP_Stopped_ApplicationExit.
625  * - field 2 A subcode, whose meaning depends on the reason
626  * code in field 1. In particular, if field 1 is
627  * ADP_Stopped_ApplicationExit then field 2 is an exit status
628  * code, as passed to the C standard library exit() function.
629  * A simulator receiving this request must notify a connected
630  * debugger, if present, and then exit with the specified status.
631  *
632  * Return
633  * No return is expected from these calls.
634  *
635  * For the A64 API, this call is identical to the behavior of
636  * the mandatory SYS_EXIT (0x18) call. If this extension is
637  * supported, then both calls must be implemented.
638  */
639  retval = semihosting_read_fields(target, 2, fields);
640  if (retval != ERROR_OK)
641  return retval;
642 
643  {
644  int type = semihosting_get_field(target, 0, fields);
645  int code = semihosting_get_field(target, 1, fields);
646 
649  exit(code);
650 
651  fprintf(stderr,
652  "semihosting: *** application exited with %d ***\n",
653  code);
654  } else {
655  fprintf(stderr, "semihosting: exception %#x\n", type);
656  }
657  }
659  semihosting->is_resumable = false;
661  }
662  break;
663 
664  case SEMIHOSTING_SYS_FLEN: /* 0x0C */
665  /*
666  * Returns the length of a specified file.
667  *
668  * Entry
669  * On entry, the PARAMETER REGISTER contains a pointer to a
670  * one-field argument block:
671  * - field 1 A handle for a previously opened, seekable file
672  * object.
673  *
674  * Return
675  * On exit, the RETURN REGISTER contains:
676  * - The current length of the file object, if the call is
677  * successful.
678  * - –1 if an error occurs.
679  */
680  if (semihosting->is_fileio) {
681  semihosting->result = -1;
682  semihosting->sys_errno = EINVAL;
683  }
684  retval = semihosting_read_fields(target, 1, fields);
685  if (retval != ERROR_OK)
686  return retval;
687 
688  {
689  int fd = semihosting_get_field(target, 0, fields);
690  struct stat buf;
691  semihosting->result = fstat(fd, &buf);
692  if (semihosting->result == -1) {
693  semihosting->sys_errno = errno;
694  LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
695  break;
696  }
697  LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
698  semihosting->result = buf.st_size;
699  }
700  break;
701 
702  case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
703  /*
704  * Returns the command line that is used for the call to the
705  * executable, that is, argc and argv.
706  *
707  * Entry
708  * On entry, the PARAMETER REGISTER points to a two-field data
709  * block to be used for returning the command string and its length:
710  * - field 1 A pointer to a buffer of at least the size that is
711  * specified in field 2.
712  * - field 2 The length of the buffer in bytes.
713  *
714  * Return
715  * On exit:
716  * If the call is successful, then the RETURN REGISTER contains 0,
717  * the PARAMETER REGISTER is unchanged, and the data block is
718  * updated as follows:
719  * - field 1 A pointer to a null-terminated string of the command
720  * line.
721  * - field 2 The length of the string in bytes.
722  * If the call is not successful, then the RETURN REGISTER
723  * contains -1.
724  *
725  * Note: The semihosting implementation might impose limits on
726  * the maximum length of the string that can be transferred.
727  * However, the implementation must be able to support a
728  * command-line length of at least 80 bytes.
729  */
730  retval = semihosting_read_fields(target, 2, fields);
731  if (retval != ERROR_OK)
732  return retval;
733 
734  {
735  uint64_t addr = semihosting_get_field(target, 0, fields);
736  size_t size = semihosting_get_field(target, 1, fields);
737 
738  char *arg = semihosting->cmdline ? semihosting->cmdline : "";
739  uint32_t len = strlen(arg) + 1;
740  if (len > size) {
741  semihosting->result = -1;
742  } else {
743  semihosting_set_field(target, len, 1, fields);
744  retval = target_write_buffer(target, addr, len,
745  (uint8_t *)arg);
746  if (retval != ERROR_OK)
747  return retval;
748  semihosting->result = 0;
749 
750  retval = semihosting_write_fields(target, 2, fields);
751  if (retval != ERROR_OK)
752  return retval;
753  }
754  LOG_DEBUG("SYS_GET_CMDLINE=[%s], %" PRId64, arg, semihosting->result);
755  }
756  break;
757 
758  case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
759  /*
760  * Returns the system stack and heap parameters.
761  *
762  * Entry
763  * On entry, the PARAMETER REGISTER contains the address of a
764  * pointer to a four-field data block. The contents of the data
765  * block are filled by the function. The following C-like
766  * pseudocode describes the layout of the block:
767  * struct block {
768  * void* heap_base;
769  * void* heap_limit;
770  * void* stack_base;
771  * void* stack_limit;
772  * };
773  *
774  * Return
775  * On exit, the PARAMETER REGISTER is unchanged and the data
776  * block has been updated.
777  */
778  retval = semihosting_read_fields(target, 1, fields);
779  if (retval != ERROR_OK)
780  return retval;
781 
782  {
783  uint64_t addr = semihosting_get_field(target, 0, fields);
784  /* tell the remote we have no idea */
785  memset(fields, 0, 4 * semihosting->word_size_bytes);
786  retval = target_write_memory(target, addr, 4,
788  fields);
789  if (retval != ERROR_OK)
790  return retval;
791  semihosting->result = 0;
792  }
793  break;
794 
795  case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
796  /*
797  * Determines whether the return code from another semihosting
798  * call is an error status or not.
799  *
800  * This call is passed a parameter block containing the error
801  * code to examine.
802  *
803  * Entry
804  * On entry, the PARAMETER REGISTER contains a pointer to a
805  * one-field data block:
806  * - field 1 The required status word to check.
807  *
808  * Return
809  * On exit, the RETURN REGISTER contains:
810  * - 0 if the status field is not an error indication
811  * - A nonzero value if the status field is an error indication.
812  */
813  retval = semihosting_read_fields(target, 1, fields);
814  if (retval != ERROR_OK)
815  return retval;
816 
817  uint64_t code = semihosting_get_field(target, 0, fields);
818  semihosting->result = (code != 0);
819  break;
820 
821  case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
822  /*
823  * Checks whether a file is connected to an interactive device.
824  *
825  * Entry
826  * On entry, the PARAMETER REGISTER contains a pointer to a
827  * one-field argument block:
828  * field 1 A handle for a previously opened file object.
829  *
830  * Return
831  * On exit, the RETURN REGISTER contains:
832  * - 1 if the handle identifies an interactive device.
833  * - 0 if the handle identifies a file.
834  * - A value other than 1 or 0 if an error occurs.
835  */
836  if (semihosting->is_fileio) {
837  semihosting->hit_fileio = true;
838  fileio_info->identifier = "isatty";
839  fileio_info->param_1 = semihosting->param;
840  } else {
841  retval = semihosting_read_fields(target, 1, fields);
842  if (retval != ERROR_OK)
843  return retval;
844  int fd = semihosting_get_field(target, 0, fields);
845  // isatty() on Windows may return any non-zero value if fd is a terminal
846  semihosting->result = isatty(fd) ? 1 : 0;
847  if (semihosting->result == 0)
848  semihosting->sys_errno = errno;
849  LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result);
850  }
851  break;
852 
853  case SEMIHOSTING_SYS_OPEN: /* 0x01 */
854  /*
855  * Opens a file on the host system.
856  *
857  * The file path is specified either as relative to the current
858  * directory of the host process, or absolute, using the path
859  * conventions of the host operating system.
860  *
861  * Semihosting implementations must support opening the special
862  * path name :semihosting-features as part of the semihosting
863  * extensions reporting mechanism.
864  *
865  * ARM targets interpret the special path name :tt as meaning
866  * the console input stream, for an open-read or the console
867  * output stream, for an open-write. Opening these streams is
868  * performed as part of the standard startup code for those
869  * applications that reference the C stdio streams. The
870  * semihosting extension SH_EXT_STDOUT_STDERR allows the
871  * semihosting caller to open separate output streams
872  * corresponding to stdout and stderr. This extension is
873  * reported using feature byte 0, bit 1. Use SYS_OPEN with
874  * the special path name :semihosting-features to access the
875  * feature bits.
876  *
877  * If this extension is supported, the implementation must
878  * support the following additional semantics to SYS_OPEN:
879  * - If the special path name :tt is opened with an fopen
880  * mode requesting write access (w, wb, w+, or w+b), then
881  * this is a request to open stdout.
882  * - If the special path name :tt is opened with a mode
883  * requesting append access (a, ab, a+, or a+b), then this is
884  * a request to open stderr.
885  *
886  * Entry
887  * On entry, the PARAMETER REGISTER contains a pointer to a
888  * three-field argument block:
889  * - field 1 A pointer to a null-terminated string containing
890  * a file or device name.
891  * - field 2 An integer that specifies the file opening mode.
892  * - field 3 An integer that gives the length of the string
893  * pointed to by field 1.
894  *
895  * The length does not include the terminating null character
896  * that must be present.
897  *
898  * Return
899  * On exit, the RETURN REGISTER contains:
900  * - A nonzero handle if the call is successful.
901  * - –1 if the call is not successful.
902  */
903  retval = semihosting_read_fields(target, 3, fields);
904  if (retval != ERROR_OK)
905  return retval;
906 
907  {
908  uint64_t addr = semihosting_get_field(target, 0, fields);
909  uint32_t mode = semihosting_get_field(target, 1, fields);
910  size_t len = semihosting_get_field(target, 2, fields);
911 
912  if (mode > 11) {
913  semihosting->result = -1;
914  semihosting->sys_errno = EINVAL;
915  break;
916  }
917  size_t basedir_len = semihosting->basedir ? strlen(semihosting->basedir) : 0;
918  uint8_t *fn = malloc(basedir_len + len + 2);
919  if (!fn) {
920  semihosting->result = -1;
921  semihosting->sys_errno = ENOMEM;
922  } else {
923  if (basedir_len > 0) {
924  strcpy((char *)fn, semihosting->basedir);
925  if (fn[basedir_len - 1] != '/')
926  fn[basedir_len++] = '/';
927  }
928  retval = target_read_memory(target, addr, 1, len, fn + basedir_len);
929  if (retval != ERROR_OK) {
930  free(fn);
931  return retval;
932  }
933  fn[basedir_len + len] = 0;
934  /* TODO: implement the :semihosting-features special file.
935  * */
936  if (semihosting->is_fileio) {
937  if (strcmp((char *)fn, ":semihosting-features") == 0) {
938  semihosting->result = -1;
939  semihosting->sys_errno = EINVAL;
940  } else if (strcmp((char *)fn, ":tt") == 0) {
941  if (mode == 0) {
942  semihosting->result = 0;
943  } else if (mode == 4) {
944  semihosting->result = 1;
945  } else if (mode == 8) {
946  semihosting->result = 2;
947  } else {
948  semihosting->result = -1;
949  semihosting->sys_errno = EINVAL;
950  }
951  } else {
952  semihosting->hit_fileio = true;
953  fileio_info->identifier = "open";
954  fileio_info->param_1 = addr;
955  fileio_info->param_2 = len;
956  fileio_info->param_3 = open_gdb_modeflags[mode];
957  fileio_info->param_4 = 0644;
958  }
959  } else {
960  if (strcmp((char *)fn, ":tt") == 0) {
961  /* Mode is:
962  * - 0-3 ("r") for stdin,
963  * - 4-7 ("w") for stdout,
964  * - 8-11 ("a") for stderr */
965  int fd;
966  if (mode < 4) {
967  fd = dup(STDIN_FILENO);
968  semihosting->stdin_fd = fd;
969  LOG_DEBUG("dup(STDIN)=%d", fd);
970  } else if (mode < 8) {
971  fd = dup(STDOUT_FILENO);
972  semihosting->stdout_fd = fd;
973  LOG_DEBUG("dup(STDOUT)=%d", fd);
974  } else {
975  fd = dup(STDERR_FILENO);
976  semihosting->stderr_fd = fd;
977  LOG_DEBUG("dup(STDERR)=%d", fd);
978  }
979  semihosting->result = fd;
980  if (fd == -1)
981  semihosting->sys_errno = errno;
982  } else {
983  /* cygwin requires the permission setting
984  * otherwise it will fail to reopen a previously
985  * written file */
986  semihosting->result = open((char *)fn,
988  0644);
989  if (semihosting->result == -1)
990  semihosting->sys_errno = errno;
991  LOG_DEBUG("open('%s')=%" PRId64, fn, semihosting->result);
992  }
993  }
994  free(fn);
995  }
996  }
997  break;
998 
999  case SEMIHOSTING_SYS_READ: /* 0x06 */
1000  /*
1001  * Reads the contents of a file into a buffer. The file position
1002  * is specified either:
1003  * - Explicitly by a SYS_SEEK.
1004  * - Implicitly one byte beyond the previous SYS_READ or
1005  * SYS_WRITE request.
1006  *
1007  * The file position is at the start of the file when it is
1008  * opened, and is lost when the file is closed. Perform the
1009  * file operation as a single action whenever possible. For
1010  * example, do not split a read of 16KB into four 4KB chunks
1011  * unless there is no alternative.
1012  *
1013  * Entry
1014  * On entry, the PARAMETER REGISTER contains a pointer to a
1015  * three-field data block:
1016  * - field 1 Contains a handle for a file previously opened
1017  * with SYS_OPEN.
1018  * - field 2 Points to a buffer.
1019  * - field 3 Contains the number of bytes to read to the buffer
1020  * from the file.
1021  *
1022  * Return
1023  * On exit, the RETURN REGISTER contains the number of bytes not
1024  * filled in the buffer (buffer_length - bytes_read) as follows:
1025  * - If the RETURN REGISTER is 0, the entire buffer was
1026  * successfully filled.
1027  * - If the RETURN REGISTER is the same as field 3, no bytes
1028  * were read (EOF can be assumed).
1029  * - If the RETURN REGISTER contains a value smaller than
1030  * field 3, the read succeeded but the buffer was only partly
1031  * filled. For interactive devices, this is the most common
1032  * return value.
1033  */
1034  retval = semihosting_read_fields(target, 3, fields);
1035  if (retval != ERROR_OK)
1036  return retval;
1037 
1038  {
1039  int fd = semihosting_get_field(target, 0, fields);
1040  uint64_t addr = semihosting_get_field(target, 1, fields);
1041  size_t len = semihosting_get_field(target, 2, fields);
1042  if (semihosting->is_fileio) {
1043  semihosting->hit_fileio = true;
1044  fileio_info->identifier = "read";
1045  fileio_info->param_1 = fd;
1046  fileio_info->param_2 = addr;
1047  fileio_info->param_3 = len;
1048  } else {
1049  uint8_t *buf = malloc(len);
1050  if (!buf) {
1051  semihosting->result = -1;
1052  semihosting->sys_errno = ENOMEM;
1053  } else {
1054  semihosting->result = semihosting_read(semihosting, fd, buf, len);
1055  LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1056  fd,
1057  addr,
1058  len,
1059  semihosting->result);
1060  if (semihosting->result >= 0) {
1061  retval = target_write_buffer(target, addr,
1063  buf);
1064  if (retval != ERROR_OK) {
1065  free(buf);
1066  return retval;
1067  }
1068  /* the number of bytes NOT filled in */
1069  semihosting->result = len -
1071  }
1072  free(buf);
1073  }
1074  }
1075  }
1076  break;
1077 
1078  case SEMIHOSTING_SYS_READC: /* 0x07 */
1079  /*
1080  * Reads a byte from the console.
1081  *
1082  * Entry
1083  * The PARAMETER REGISTER must contain 0. There are no other
1084  * parameters or values possible.
1085  *
1086  * Return
1087  * On exit, the RETURN REGISTER contains the byte read from
1088  * the console.
1089  */
1090  if (semihosting->is_fileio) {
1091  LOG_ERROR("SYS_READC not supported by semihosting fileio");
1092  return ERROR_FAIL;
1093  }
1095  LOG_DEBUG("getchar()=%" PRId64, semihosting->result);
1096  break;
1097 
1098  case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
1099  /*
1100  * Deletes a specified file on the host filing system.
1101  *
1102  * Entry
1103  * On entry, the PARAMETER REGISTER contains a pointer to a
1104  * two-field argument block:
1105  * - field 1 Points to a null-terminated string that gives the
1106  * path name of the file to be deleted.
1107  * - field 2 The length of the string.
1108  *
1109  * Return
1110  * On exit, the RETURN REGISTER contains:
1111  * - 0 if the delete is successful
1112  * - A nonzero, host-specific error code if the delete fails.
1113  */
1114  retval = semihosting_read_fields(target, 2, fields);
1115  if (retval != ERROR_OK)
1116  return retval;
1117 
1118  {
1119  uint64_t addr = semihosting_get_field(target, 0, fields);
1120  size_t len = semihosting_get_field(target, 1, fields);
1121  if (semihosting->is_fileio) {
1122  semihosting->hit_fileio = true;
1123  fileio_info->identifier = "unlink";
1124  fileio_info->param_1 = addr;
1125  fileio_info->param_2 = len;
1126  } else {
1127  uint8_t *fn = malloc(len + 1);
1128  if (!fn) {
1129  semihosting->result = -1;
1130  semihosting->sys_errno = ENOMEM;
1131  } else {
1132  retval = target_read_memory(target, addr, 1, len, fn);
1133  if (retval != ERROR_OK) {
1134  free(fn);
1135  return retval;
1136  }
1137  fn[len] = 0;
1138  semihosting->result = remove((char *)fn);
1139  if (semihosting->result == -1)
1140  semihosting->sys_errno = errno;
1141  LOG_DEBUG("remove('%s')=%" PRId64, fn, semihosting->result);
1142 
1143  free(fn);
1144  }
1145  }
1146  }
1147  break;
1148 
1149  case SEMIHOSTING_SYS_RENAME: /* 0x0F */
1150  /*
1151  * Renames a specified file.
1152  *
1153  * Entry
1154  * On entry, the PARAMETER REGISTER contains a pointer to a
1155  * four-field data block:
1156  * - field 1 A pointer to the name of the old file.
1157  * - field 2 The length of the old filename.
1158  * - field 3 A pointer to the new filename.
1159  * - field 4 The length of the new filename. Both strings are
1160  * null-terminated.
1161  *
1162  * Return
1163  * On exit, the RETURN REGISTER contains:
1164  * - 0 if the rename is successful.
1165  * - A nonzero, host-specific error code if the rename fails.
1166  */
1167  retval = semihosting_read_fields(target, 4, fields);
1168  if (retval != ERROR_OK)
1169  return retval;
1170 
1171  {
1172  uint64_t addr1 = semihosting_get_field(target, 0, fields);
1173  size_t len1 = semihosting_get_field(target, 1, fields);
1174  uint64_t addr2 = semihosting_get_field(target, 2, fields);
1175  size_t len2 = semihosting_get_field(target, 3, fields);
1176  if (semihosting->is_fileio) {
1177  semihosting->hit_fileio = true;
1178  fileio_info->identifier = "rename";
1179  fileio_info->param_1 = addr1;
1180  fileio_info->param_2 = len1;
1181  fileio_info->param_3 = addr2;
1182  fileio_info->param_4 = len2;
1183  } else {
1184  uint8_t *fn1 = malloc(len1 + 1);
1185  uint8_t *fn2 = malloc(len2 + 1);
1186  if (!fn1 || !fn2) {
1187  free(fn1);
1188  free(fn2);
1189  semihosting->result = -1;
1190  semihosting->sys_errno = ENOMEM;
1191  } else {
1192  retval = target_read_memory(target, addr1, 1, len1, fn1);
1193  if (retval != ERROR_OK) {
1194  free(fn1);
1195  free(fn2);
1196  return retval;
1197  }
1198  retval = target_read_memory(target, addr2, 1, len2, fn2);
1199  if (retval != ERROR_OK) {
1200  free(fn1);
1201  free(fn2);
1202  return retval;
1203  }
1204  fn1[len1] = 0;
1205  fn2[len2] = 0;
1206  semihosting->result = rename((char *)fn1, (char *)fn2);
1207  // rename() on Windows returns nonzero on error
1208  if (semihosting->result != 0)
1209  semihosting->sys_errno = errno;
1210  LOG_DEBUG("rename('%s', '%s')=%" PRId64 " %d", fn1, fn2, semihosting->result, errno);
1211  free(fn1);
1212  free(fn2);
1213  }
1214  }
1215  }
1216  break;
1217 
1218  case SEMIHOSTING_SYS_SEEK: /* 0x0A */
1219  /*
1220  * Seeks to a specified position in a file using an offset
1221  * specified from the start of the file. The file is assumed
1222  * to be a byte array and the offset is given in bytes.
1223  *
1224  * Entry
1225  * On entry, the PARAMETER REGISTER contains a pointer to a
1226  * two-field data block:
1227  * - field 1 A handle for a seekable file object.
1228  * - field 2 The absolute byte position to seek to.
1229  *
1230  * Return
1231  * On exit, the RETURN REGISTER contains:
1232  * - 0 if the request is successful.
1233  * - A negative value if the request is not successful.
1234  * Use SYS_ERRNO to read the value of the host errno variable
1235  * describing the error.
1236  *
1237  * Note: The effect of seeking outside the current extent of
1238  * the file object is undefined.
1239  */
1240  retval = semihosting_read_fields(target, 2, fields);
1241  if (retval != ERROR_OK)
1242  return retval;
1243 
1244  {
1245  int fd = semihosting_get_field(target, 0, fields);
1246  off_t pos = semihosting_get_field(target, 1, fields);
1247  if (semihosting->is_fileio) {
1248  semihosting->hit_fileio = true;
1249  fileio_info->identifier = "lseek";
1250  fileio_info->param_1 = fd;
1251  fileio_info->param_2 = pos;
1252  fileio_info->param_3 = SEEK_SET;
1253  } else {
1254  semihosting->result = lseek(fd, pos, SEEK_SET);
1255  if (semihosting->result == -1)
1256  semihosting->sys_errno = errno;
1257  LOG_DEBUG("lseek(%d, %d)=%" PRId64, fd, (int)pos, semihosting->result);
1258  if (semihosting->result == pos)
1259  semihosting->result = 0;
1260  }
1261  }
1262  break;
1263 
1264  case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1265  /*
1266  * Passes a command to the host command-line interpreter.
1267  * This enables you to execute a system command such as dir,
1268  * ls, or pwd. The terminal I/O is on the host, and is not
1269  * visible to the target.
1270  *
1271  * Entry
1272  * On entry, the PARAMETER REGISTER contains a pointer to a
1273  * two-field argument block:
1274  * - field 1 Points to a string to be passed to the host
1275  * command-line interpreter.
1276  * - field 2 The length of the string.
1277  *
1278  * Return
1279  * On exit, the RETURN REGISTER contains the return status.
1280  */
1281 
1282  /* Provide SYS_SYSTEM functionality. Uses the
1283  * libc system command, there may be a reason *NOT*
1284  * to use this, but as I can't think of one, I
1285  * implemented it this way.
1286  */
1287  retval = semihosting_read_fields(target, 2, fields);
1288  if (retval != ERROR_OK)
1289  return retval;
1290 
1291  {
1292  uint64_t addr = semihosting_get_field(target, 0, fields);
1293  size_t len = semihosting_get_field(target, 1, fields);
1294  if (semihosting->is_fileio) {
1295  semihosting->hit_fileio = true;
1296  fileio_info->identifier = "system";
1297  fileio_info->param_1 = addr;
1298  fileio_info->param_2 = len;
1299  } else {
1300  uint8_t *cmd = malloc(len + 1);
1301  if (!cmd) {
1302  semihosting->result = -1;
1303  semihosting->sys_errno = ENOMEM;
1304  } else {
1305  retval = target_read_memory(target,
1306  addr,
1307  1,
1308  len,
1309  cmd);
1310  if (retval != ERROR_OK) {
1311  free(cmd);
1312  return retval;
1313  }
1314  cmd[len] = 0;
1315  semihosting->result = system((const char *)cmd);
1316  LOG_DEBUG("system('%s')=%" PRId64, cmd, semihosting->result);
1317 
1318  free(cmd);
1319  }
1320  }
1321  }
1322  break;
1323 
1324  case SEMIHOSTING_SYS_TIME: /* 0x11 */
1325  /*
1326  * Returns the number of seconds since 00:00 January 1, 1970.
1327  * This value is real-world time, regardless of any debug agent
1328  * configuration.
1329  *
1330  * Entry
1331  * There are no parameters.
1332  *
1333  * Return
1334  * On exit, the RETURN REGISTER contains the number of seconds.
1335  */
1336  semihosting->result = time(NULL);
1337  break;
1338 
1339  case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1340  /*
1341  * Writes the contents of a buffer to a specified file at the
1342  * current file position. The file position is specified either:
1343  * - Explicitly, by a SYS_SEEK.
1344  * - Implicitly as one byte beyond the previous SYS_READ or
1345  * SYS_WRITE request.
1346  *
1347  * The file position is at the start of the file when the file
1348  * is opened, and is lost when the file is closed.
1349  *
1350  * Perform the file operation as a single action whenever
1351  * possible. For example, do not split a write of 16KB into
1352  * four 4KB chunks unless there is no alternative.
1353  *
1354  * Entry
1355  * On entry, the PARAMETER REGISTER contains a pointer to a
1356  * three-field data block:
1357  * - field 1 Contains a handle for a file previously opened
1358  * with SYS_OPEN.
1359  * - field 2 Points to the memory containing the data to be written.
1360  * - field 3 Contains the number of bytes to be written from
1361  * the buffer to the file.
1362  *
1363  * Return
1364  * On exit, the RETURN REGISTER contains:
1365  * - 0 if the call is successful.
1366  * - The number of bytes that are not written, if there is an error.
1367  */
1368  retval = semihosting_read_fields(target, 3, fields);
1369  if (retval != ERROR_OK)
1370  return retval;
1371 
1372  {
1373  int fd = semihosting_get_field(target, 0, fields);
1374  uint64_t addr = semihosting_get_field(target, 1, fields);
1375  size_t len = semihosting_get_field(target, 2, fields);
1376  if (semihosting->is_fileio) {
1377  semihosting->hit_fileio = true;
1378  fileio_info->identifier = "write";
1379  fileio_info->param_1 = fd;
1380  fileio_info->param_2 = addr;
1381  fileio_info->param_3 = len;
1382  } else {
1383  uint8_t *buf = malloc(len);
1384  if (!buf) {
1385  semihosting->result = -1;
1386  semihosting->sys_errno = ENOMEM;
1387  } else {
1388  retval = target_read_buffer(target, addr, len, buf);
1389  if (retval != ERROR_OK) {
1390  free(buf);
1391  return retval;
1392  }
1393  semihosting->result = semihosting_write(semihosting, fd, buf, len);
1394  LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1395  fd,
1396  addr,
1397  len,
1398  semihosting->result);
1399  if (semihosting->result >= 0) {
1400  /* The number of bytes that are NOT written.
1401  * */
1402  semihosting->result = len -
1404  }
1405 
1406  free(buf);
1407  }
1408  }
1409  }
1410  break;
1411 
1412  case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1413  /*
1414  * Writes a character byte, pointed to by the PARAMETER REGISTER,
1415  * to the debug channel. When executed under a semihosting
1416  * debugger, the character appears on the host debugger console.
1417  *
1418  * Entry
1419  * On entry, the PARAMETER REGISTER contains a pointer to the
1420  * character.
1421  *
1422  * Return
1423  * None. The RETURN REGISTER is corrupted.
1424  */
1425  if (semihosting->is_fileio) {
1426  semihosting->hit_fileio = true;
1427  fileio_info->identifier = "write";
1428  fileio_info->param_1 = 1;
1429  fileio_info->param_2 = semihosting->param;
1430  fileio_info->param_3 = 1;
1431  } else {
1432  uint64_t addr = semihosting->param;
1433  unsigned char c;
1434  retval = target_read_memory(target, addr, 1, 1, &c);
1435  if (retval != ERROR_OK)
1436  return retval;
1438  semihosting->result = 0;
1439  }
1440  break;
1441 
1442  case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1443  /*
1444  * Writes a null-terminated string to the debug channel.
1445  * When executed under a semihosting debugger, the characters
1446  * appear on the host debugger console.
1447  *
1448  * Entry
1449  * On entry, the PARAMETER REGISTER contains a pointer to the
1450  * first byte of the string.
1451  *
1452  * Return
1453  * None. The RETURN REGISTER is corrupted.
1454  */
1455  if (semihosting->is_fileio) {
1456  size_t count = 0;
1457  uint64_t addr = semihosting->param;
1458  for (;; addr++) {
1459  unsigned char c;
1460  retval = target_read_memory(target, addr, 1, 1, &c);
1461  if (retval != ERROR_OK)
1462  return retval;
1463  if (c == '\0')
1464  break;
1465  count++;
1466  }
1467  semihosting->hit_fileio = true;
1468  fileio_info->identifier = "write";
1469  fileio_info->param_1 = 1;
1470  fileio_info->param_2 = semihosting->param;
1471  fileio_info->param_3 = count;
1472  } else {
1473  uint64_t addr = semihosting->param;
1474  do {
1475  unsigned char c;
1476  retval = target_read_memory(target, addr++, 1, 1, &c);
1477  if (retval != ERROR_OK)
1478  return retval;
1479  if (!c)
1480  break;
1482  } while (1);
1483  semihosting->result = 0;
1484  }
1485  break;
1486 
1508  if (retval != ERROR_NOT_IMPLEMENTED)
1509  break;
1510  /* If custom user command not handled, we are looking for the TCL handler */
1511  }
1512 
1513  assert(!semihosting_user_op_params);
1514  retval = semihosting_read_fields(target, 2, fields);
1515  if (retval != ERROR_OK) {
1516  LOG_ERROR("Failed to read fields for user defined command"
1517  " op=0x%x", semihosting->op);
1518  return retval;
1519  }
1520 
1521  uint64_t addr = semihosting_get_field(target, 0, fields);
1522 
1523  size_t len = semihosting_get_field(target, 1, fields);
1525  LOG_ERROR("The maximum length for user defined command "
1526  "parameter is %u, received length is %zu (op=0x%x)",
1528  len,
1529  semihosting->op);
1530  return ERROR_FAIL;
1531  }
1532 
1533  semihosting_user_op_params = malloc(len + 1);
1535  return ERROR_FAIL;
1536  semihosting_user_op_params[len] = 0;
1537 
1538  retval = target_read_buffer(target, addr, len,
1539  (uint8_t *)(semihosting_user_op_params));
1540  if (retval != ERROR_OK) {
1541  LOG_ERROR("Failed to read from target, semihosting op=0x%x (%s)",
1542  semihosting->op,
1546  return retval;
1547  }
1548 
1552  semihosting->result = 0;
1553  break;
1554 
1555  case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1556  /*
1557  * Returns the number of elapsed target ticks since execution
1558  * started.
1559  * Use SYS_TICKFREQ to determine the tick frequency.
1560  *
1561  * Entry (32-bit)
1562  * On entry, the PARAMETER REGISTER points to a two-field data
1563  * block to be used for returning the number of elapsed ticks:
1564  * - field 1 The least significant field and is at the low address.
1565  * - field 2 The most significant field and is at the high address.
1566  *
1567  * Entry (64-bit)
1568  * On entry the PARAMETER REGISTER points to a one-field data
1569  * block to be used for returning the number of elapsed ticks:
1570  * - field 1 The number of elapsed ticks as a 64-bit value.
1571  *
1572  * Return
1573  * On exit:
1574  * - On success, the RETURN REGISTER contains 0, the PARAMETER
1575  * REGISTER is unchanged, and the data block pointed to by the
1576  * PARAMETER REGISTER is filled in with the number of elapsed
1577  * ticks.
1578  * - On failure, the RETURN REGISTER contains -1, and the
1579  * PARAMETER REGISTER contains -1.
1580  *
1581  * Note: Some semihosting implementations might not support this
1582  * semihosting operation, and they always return -1 in the
1583  * RETURN REGISTER.
1584  */
1585 
1586  case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1587  /*
1588  * Returns the tick frequency.
1589  *
1590  * Entry
1591  * The PARAMETER REGISTER must contain 0 on entry to this routine.
1592  *
1593  * Return
1594  * On exit, the RETURN REGISTER contains either:
1595  * - The number of ticks per second.
1596  * - –1 if the target does not know the value of one tick.
1597  *
1598  * Note: Some semihosting implementations might not support
1599  * this semihosting operation, and they always return -1 in the
1600  * RETURN REGISTER.
1601  */
1602 
1603  case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1604  /*
1605  * Returns a temporary name for a file identified by a system
1606  * file identifier.
1607  *
1608  * Entry
1609  * On entry, the PARAMETER REGISTER contains a pointer to a
1610  * three-word argument block:
1611  * - field 1 A pointer to a buffer.
1612  * - field 2 A target identifier for this filename. Its value
1613  * must be an integer in the range 0-255.
1614  * - field 3 Contains the length of the buffer. The length must
1615  * be at least the value of L_tmpnam on the host system.
1616  *
1617  * Return
1618  * On exit, the RETURN REGISTER contains:
1619  * - 0 if the call is successful.
1620  * - –1 if an error occurs.
1621  *
1622  * The buffer pointed to by the PARAMETER REGISTER contains
1623  * the filename, prefixed with a suitable directory name.
1624  * If you use the same target identifier again, the same
1625  * filename is returned.
1626  *
1627  * Note: The returned string must be null-terminated.
1628  */
1629 
1630  default:
1631  fprintf(stderr, "semihosting: unsupported call %#x\n",
1632  (unsigned int)semihosting->op);
1633  semihosting->result = -1;
1635  }
1636 
1637  if (!semihosting->hit_fileio) {
1638  retval = semihosting->post_result(target);
1639  if (retval != ERROR_OK) {
1640  LOG_ERROR("Failed to post semihosting result");
1641  return retval;
1642  }
1643  }
1644 
1645  return ERROR_OK;
1646 }
1647 
1648 /* -------------------------------------------------------------------------
1649  * Local functions. */
1650 
1652  struct gdb_fileio_info *fileio_info)
1653 {
1655  if (!semihosting)
1656  return ERROR_FAIL;
1657 
1658  /*
1659  * To avoid unnecessary duplication, semihosting prepares the
1660  * fileio_info structure out-of-band when the target halts. See
1661  * do_semihosting for more detail.
1662  */
1664  return ERROR_FAIL;
1665 
1666  return ERROR_OK;
1667 }
1668 
1670  int fileio_errno, bool ctrl_c)
1671 {
1672  struct gdb_fileio_info *fileio_info = target->fileio_info;
1674  if (!semihosting)
1675  return ERROR_FAIL;
1676 
1677  /* clear pending status */
1678  semihosting->hit_fileio = false;
1679 
1681 
1682  /*
1683  * Some fileio results do not match up with what the semihosting
1684  * operation expects; for these operations, we munge the results
1685  * below:
1686  */
1687  switch (semihosting->op) {
1688  case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1689  case SEMIHOSTING_SYS_READ: /* 0x06 */
1690  if (result < 0)
1691  semihosting->result = fileio_info->param_3; /* Zero bytes read/written. */
1692  else
1693  semihosting->result = (int64_t)fileio_info->param_3 - result;
1694  break;
1695 
1696  case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1697  if (result > 0)
1698  semihosting->result = 0;
1699  break;
1700  }
1701 
1702  bool fileio_failed = false;
1704  fileio_failed = (semihosting->result == 0);
1705  else if (semihosting->op == SEMIHOSTING_SYS_RENAME)
1706  fileio_failed = (semihosting->result != 0);
1707  else
1708  fileio_failed = (semihosting->result == -1);
1709 
1710  if (fileio_failed)
1711  semihosting->sys_errno = fileio_errno;
1712 
1713  return semihosting->post_result(target);
1714 }
1715 
1716 /* -------------------------------------------------------------------------
1717  * Utility functions. */
1718 
1723  uint8_t *fields)
1724 {
1726  /* Use 4-byte multiples to trigger fast memory access. */
1728  number * (semihosting->word_size_bytes / 4), fields);
1729 }
1730 
1734 static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields)
1735 {
1737  /* Use 4-byte multiples to trigger fast memory access. */
1739  number * (semihosting->word_size_bytes / 4), fields);
1740 }
1741 
1745 uint64_t semihosting_get_field(struct target *target, size_t index,
1746  uint8_t *fields)
1747 {
1749  if (semihosting->word_size_bytes == 8)
1750  return target_buffer_get_u64(target, fields + (index * 8));
1751  else
1752  return target_buffer_get_u32(target, fields + (index * 4));
1753 }
1754 
1758 static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields)
1759 {
1761  if (semihosting->word_size_bytes == 8)
1762  target_buffer_set_u64(target, fields + (index * 8), value);
1763  else
1764  target_buffer_set_u32(target, fields + (index * 4), value);
1765 }
1766 
1767 /* -------------------------------------------------------------------------
1768  * Semihosting redirect over TCP structs and functions */
1769 
1771 {
1773  service->semihosting->tcp_connection = connection;
1774 
1775  return ERROR_OK;
1776 }
1777 
1779 {
1781 
1782  if (!connection->input_pending) {
1783  /* consume received data, not for semihosting IO */
1784  const int buf_len = 100;
1785  char buf[buf_len];
1786  int bytes_read = connection_read(connection, buf, buf_len);
1787 
1788  if (bytes_read == 0) {
1790  } else if (bytes_read == -1) {
1791  LOG_ERROR("error during read: %s", strerror(errno));
1793  }
1794  } else if (service->error != ERROR_OK) {
1796  }
1797 
1798  return ERROR_OK;
1799 }
1800 
1802 {
1804  if (service)
1805  free(service->name);
1806 
1807  return ERROR_OK;
1808 }
1809 
1811 {
1813  return;
1814 
1818 
1819 }
1820 
1821 static const struct service_driver semihosting_service_driver = {
1822  .name = "semihosting",
1823  .new_connection_during_keep_alive_handler = NULL,
1824  .new_connection_handler = semihosting_service_new_connection_handler,
1825  .input_handler = semihosting_service_input_handler,
1826  .connection_closed_handler = semihosting_service_connection_closed_handler,
1827  .keep_client_alive_handler = NULL,
1828 };
1829 
1830 /* -------------------------------------------------------------------------
1831  * Common semihosting commands handlers. */
1832 
1833 COMMAND_HANDLER(handle_common_semihosting_command)
1834 {
1836 
1837  if (!target) {
1838  LOG_ERROR("No target selected");
1839  return ERROR_FAIL;
1840  }
1841 
1843  if (!semihosting) {
1844  command_print(CMD, "semihosting not supported for current target");
1845  return ERROR_FAIL;
1846  }
1847 
1848  if (CMD_ARGC > 0) {
1849  int is_active;
1850 
1852 
1853  if (!target_was_examined(target)) {
1854  LOG_ERROR("Target not examined yet");
1855  return ERROR_FAIL;
1856  }
1857 
1859  LOG_ERROR("Failed to Configure semihosting");
1860  return ERROR_FAIL;
1861  }
1862 
1863  /* FIXME never let that "catch" be dropped! (???) */
1865  }
1866 
1867  command_print(CMD, "semihosting is %s",
1869  ? "enabled" : "disabled");
1870 
1871  return ERROR_OK;
1872 }
1873 
1874 COMMAND_HANDLER(handle_common_semihosting_redirect_command)
1875 {
1877 
1878  if (!target) {
1879  LOG_ERROR("No target selected");
1880  return ERROR_FAIL;
1881  }
1882 
1884  if (!semihosting) {
1885  command_print(CMD, "semihosting not supported for current target");
1886  return ERROR_FAIL;
1887  }
1888 
1889  if (!semihosting->is_active) {
1890  command_print(CMD, "semihosting not yet enabled for current target");
1891  return ERROR_FAIL;
1892  }
1893 
1894  enum semihosting_redirect_config cfg;
1895  const char *port;
1896 
1897  if (CMD_ARGC < 1)
1899 
1900  if (strcmp(CMD_ARGV[0], "disable") == 0) {
1902  if (CMD_ARGC > 1)
1904  } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
1905  if (CMD_ARGC < 2 || CMD_ARGC > 3)
1907 
1908  port = CMD_ARGV[1];
1909 
1911  if (CMD_ARGC == 3) {
1912  if (strcmp(CMD_ARGV[2], "debug") == 0)
1914  else if (strcmp(CMD_ARGV[2], "stdio") == 0)
1916  else if (strcmp(CMD_ARGV[2], "all") != 0)
1918  }
1919  } else {
1921  }
1922 
1925 
1926  if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) {
1928  calloc(1, sizeof(struct semihosting_tcp_service));
1929  if (!service) {
1930  LOG_ERROR("Failed to allocate semihosting TCP service.");
1931  return ERROR_FAIL;
1932  }
1933 
1934  service->semihosting = semihosting;
1935 
1936  service->name = alloc_printf("%s semihosting service", target_name(target));
1937  if (!service->name) {
1938  LOG_ERROR("Out of memory");
1939  free(service);
1940  return ERROR_FAIL;
1941  }
1942 
1944  port, 1, service);
1945 
1946  if (ret != ERROR_OK) {
1947  LOG_ERROR("failed to initialize %s", service->name);
1948  free(service->name);
1949  free(service);
1950  return ERROR_FAIL;
1951  }
1952  }
1953 
1954  semihosting->redirect_cfg = cfg;
1955 
1956  return ERROR_OK;
1957 }
1958 
1959 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1960 {
1962 
1963  if (!target) {
1964  LOG_ERROR("No target selected");
1965  return ERROR_FAIL;
1966  }
1967 
1969  if (!semihosting) {
1970  command_print(CMD, "semihosting not supported for current target");
1971  return ERROR_FAIL;
1972  }
1973 
1974  if (!semihosting->is_active) {
1975  command_print(CMD, "semihosting not yet enabled for current target");
1976  return ERROR_FAIL;
1977  }
1978 
1979  if (CMD_ARGC > 0)
1981 
1982  command_print(CMD, "semihosting fileio is %s",
1984  ? "enabled" : "disabled");
1985 
1986  return ERROR_OK;
1987 }
1988 
1989 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1990 {
1992  unsigned int i;
1993 
1994  if (!target) {
1995  LOG_ERROR("No target selected");
1996  return ERROR_FAIL;
1997  }
1998 
2000  if (!semihosting) {
2001  command_print(CMD, "semihosting not supported for current target");
2002  return ERROR_FAIL;
2003  }
2004 
2005  free(semihosting->cmdline);
2006  semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
2007 
2008  for (i = 1; i < CMD_ARGC; i++) {
2009  char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
2010  if (!cmdline)
2011  break;
2012  free(semihosting->cmdline);
2014  }
2015 
2016  command_print(CMD, "semihosting command line is [%s]",
2017  semihosting->cmdline);
2018 
2019  return ERROR_OK;
2020 }
2021 
2022 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
2023 {
2025 
2026  if (!target) {
2027  LOG_ERROR("No target selected");
2028  return ERROR_FAIL;
2029  }
2030 
2032  if (!semihosting) {
2033  command_print(CMD, "semihosting not supported for current target");
2034  return ERROR_FAIL;
2035  }
2036 
2037  if (!semihosting->is_active) {
2038  command_print(CMD, "semihosting not yet enabled for current target");
2039  return ERROR_FAIL;
2040  }
2041 
2042  if (CMD_ARGC > 0)
2044 
2045  command_print(CMD, "semihosting resumable exit is %s",
2047  ? "enabled" : "disabled");
2048 
2049  return ERROR_OK;
2050 }
2051 
2052 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
2053 {
2056 
2057  if (CMD_ARGC)
2059 
2060  if (!semihosting->is_active) {
2061  LOG_ERROR("semihosting not yet enabled for current target");
2062  return ERROR_FAIL;
2063  }
2064 
2066  LOG_ERROR("This command is usable only from a registered user "
2067  "semihosting event callback.");
2068  return ERROR_FAIL;
2069  }
2070 
2072 
2073  return ERROR_OK;
2074 }
2075 
2076 COMMAND_HANDLER(handle_common_semihosting_basedir_command)
2077 {
2079 
2080  if (CMD_ARGC > 1)
2082 
2083  if (!target) {
2084  LOG_ERROR("No target selected");
2085  return ERROR_FAIL;
2086  }
2087 
2089  if (!semihosting) {
2090  command_print(CMD, "semihosting not supported for current target");
2091  return ERROR_FAIL;
2092  }
2093 
2094  if (!semihosting->is_active) {
2095  command_print(CMD, "semihosting not yet enabled for current target");
2096  return ERROR_FAIL;
2097  }
2098 
2099  if (CMD_ARGC > 0) {
2100  free(semihosting->basedir);
2101  semihosting->basedir = strdup(CMD_ARGV[0]);
2102  if (!semihosting->basedir) {
2103  command_print(CMD, "semihosting failed to allocate memory for basedir!");
2104  return ERROR_FAIL;
2105  }
2106  }
2107 
2108  command_print(CMD, "semihosting base dir: %s",
2110 
2111  return ERROR_OK;
2112 }
2113 
2115  {
2116  .name = "semihosting",
2117  .handler = handle_common_semihosting_command,
2118  .mode = COMMAND_EXEC,
2119  .usage = "['enable'|'disable']",
2120  .help = "activate support for semihosting operations",
2121  },
2122  {
2123  .name = "semihosting_redirect",
2124  .handler = handle_common_semihosting_redirect_command,
2125  .mode = COMMAND_EXEC,
2126  .usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2127  .help = "redirect semihosting IO",
2128  },
2129  {
2130  .name = "semihosting_cmdline",
2131  .handler = handle_common_semihosting_cmdline,
2132  .mode = COMMAND_EXEC,
2133  .usage = "arguments",
2134  .help = "command line arguments to be passed to program",
2135  },
2136  {
2137  .name = "semihosting_fileio",
2138  .handler = handle_common_semihosting_fileio_command,
2139  .mode = COMMAND_EXEC,
2140  .usage = "['enable'|'disable']",
2141  .help = "activate support for semihosting fileio operations",
2142  },
2143  {
2144  .name = "semihosting_resexit",
2145  .handler = handle_common_semihosting_resumable_exit_command,
2146  .mode = COMMAND_EXEC,
2147  .usage = "['enable'|'disable']",
2148  .help = "activate support for semihosting resumable exit",
2149  },
2150  {
2151  .name = "semihosting_read_user_param",
2152  .handler = handle_common_semihosting_read_user_param_command,
2153  .mode = COMMAND_EXEC,
2154  .usage = "",
2155  .help = "read parameters in semihosting-user-cmd-0x10X callbacks",
2156  },
2157  {
2158  .name = "semihosting_basedir",
2159  .handler = handle_common_semihosting_basedir_command,
2160  .mode = COMMAND_EXEC,
2161  .usage = "[dir]",
2162  .help = "set the base directory for semihosting I/O operations",
2163  },
2165 };
static int post_result(struct target *target)
enum arm_mode mode
Definition: armv4_5.c:281
Support functions to access arbitrary bits in a byte array.
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:348
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:371
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:400
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_ENABLE(in, out)
parses an enable/disable command argument
Definition: command.h:531
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:251
@ COMMAND_EXEC
Definition: command.h:40
uint32_t size
Size of dw_spi_transaction::buffer.
Definition: dw-spi-helper.h:4
enum esirisc_reg_num number
Definition: esirisc.c:87
uint8_t type
Definition: esp_usb_jtag.c:0
int gdb_get_actual_connections(void)
Definition: gdb_server.c:4195
void log_socket_error(const char *socket_desc)
Definition: log.c:496
char * alloc_printf(const char *format,...)
Definition: log.c:376
#define ERROR_NOT_IMPLEMENTED
Definition: log.h:178
#define ERROR_FAIL
Definition: log.h:174
#define LOG_ERROR(expr ...)
Definition: log.h:133
#define LOG_DEBUG(expr ...)
Definition: log.h:110
#define ERROR_OK
Definition: log.h:168
#define O_BINARY
Definition: replacements.h:37
#define ENOTSUP
Definition: replacements.h:31
target_addr_t addr
Start address to search for the control block.
Definition: rtt/rtt.c:28
int semihosting_common_init(struct target *target, void *setup, void *post_result)
Initialize common semihosting support.
static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size)
static const int open_host_modeflags[12]
static int semihosting_common_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c)
const struct command_registration semihosting_common_handlers[]
static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields)
Store a field in the buffer, considering register size and endianness.
static int semihosting_service_connection_closed_handler(struct connection *connection)
uint64_t semihosting_get_field(struct target *target, size_t index, uint8_t *fields)
Extract a field from the buffer, considering register size and endianness.
static const int open_gdb_modeflags[12]
static const struct service_driver semihosting_service_driver
static int semihosting_service_input_handler(struct connection *connection)
static int semihosting_getchar(struct semihosting *semihosting, int fd)
COMMAND_HANDLER(handle_common_semihosting_command)
static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
static const char * semihosting_opcode_to_str(const uint64_t opcode)
Convert the syscall opcode to a human-readable string.
static int semihosting_putchar(struct semihosting *semihosting, int fd, int c)
static int semihosting_service_new_connection_handler(struct connection *connection)
static char * semihosting_user_op_params
User operation parameter string storage buffer.
int semihosting_common(struct target *target)
Portable implementation of ARM semihosting calls.
static ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size)
static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size)
int semihosting_read_fields(struct target *target, size_t number, uint8_t *fields)
Read all fields of a command from target to buffer.
static bool semihosting_is_redirected(struct semihosting *semihosting, int fd)
static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields)
Write all fields of a command from buffer to target.
static void semihosting_tcp_close_cnx(struct semihosting *semihosting)
static int semihosting_common_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
@ TARGET_O_WRONLY
@ TARGET_O_TRUNC
@ TARGET_O_RDWR
@ TARGET_O_RDONLY
@ TARGET_O_CREAT
@ TARGET_O_APPEND
semihosting_redirect_config
@ SEMIHOSTING_REDIRECT_CFG_ALL
@ SEMIHOSTING_REDIRECT_CFG_DEBUG
@ SEMIHOSTING_REDIRECT_CFG_NONE
@ SEMIHOSTING_REDIRECT_CFG_STDIO
@ ADP_STOPPED_RUN_TIME_ERROR
@ ADP_STOPPED_APPLICATION_EXIT
#define SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH
Maximum allowed Tcl command segment length in bytes.
@ SEMIHOSTING_SYS_TICKFREQ
@ SEMIHOSTING_USER_CMD_0X107
@ SEMIHOSTING_SYS_EXIT
@ SEMIHOSTING_SYS_ISERROR
@ SEMIHOSTING_USER_CMD_0X1FF
@ SEMIHOSTING_SYS_WRITE
@ SEMIHOSTING_SYS_FLEN
@ SEMIHOSTING_SYS_GET_CMDLINE
@ SEMIHOSTING_SYS_EXIT_EXTENDED
@ SEMIHOSTING_ARM_RESERVED_END
@ SEMIHOSTING_SYS_REMOVE
@ SEMIHOSTING_SYS_SEEK
@ SEMIHOSTING_ARM_RESERVED_START
@ SEMIHOSTING_SYS_TMPNAM
@ SEMIHOSTING_SYS_TIME
@ SEMIHOSTING_SYS_CLOCK
@ SEMIHOSTING_SYS_WRITEC
@ SEMIHOSTING_SYS_ERRNO
@ SEMIHOSTING_SYS_ISTTY
@ SEMIHOSTING_SYS_HEAPINFO
@ SEMIHOSTING_SYS_WRITE0
@ SEMIHOSTING_SYS_ELAPSED
@ SEMIHOSTING_SYS_READ
@ SEMIHOSTING_SYS_SYSTEM
@ SEMIHOSTING_SYS_CLOSE
@ SEMIHOSTING_SYS_READC
@ SEMIHOSTING_SYS_OPEN
@ SEMIHOSTING_SYS_RENAME
@ SEMIHOSTING_USER_CMD_0X100
int connection_write(struct connection *connection, const void *data, int len)
Definition: server.c:733
int connection_read(struct connection *connection, void *data, int len)
Definition: server.c:745
int remove_service(const char *name, const char *port)
Definition: server.c:355
int add_service(const struct service_driver *driver, const char *port, int max_connections, void *priv)
Definition: server.c:198
#define ERROR_SERVER_REMOTE_CLOSED
Definition: server.h:119
const char * name
Definition: command.h:234
struct service * service
Definition: server.h:41
bool input_pending
Definition: server.h:42
uint64_t param_1
Definition: target.h:222
uint64_t param_4
Definition: target.h:225
uint64_t param_3
Definition: target.h:224
char * identifier
Definition: target.h:221
uint64_t param_2
Definition: target.h:223
struct semihosting * semihosting
bool is_resumable
Most are resumable, except the two exit calls.
int stdin_fd
Semihosting STDIO file descriptors.
bool has_resumable_exit
When SEMIHOSTING_SYS_EXIT is called outside a debug session, things are simple, the openocd process c...
int(* setup)(struct target *target, int enable)
int(* post_result)(struct target *target)
bool hit_fileio
A flag reporting whether semihosting fileio operation is active.
size_t word_size_bytes
The Target (hart) word size; 8 for 64-bits targets.
bool is_fileio
A flag reporting whether semihosting fileio is active.
int(* user_command_extension)(struct target *target)
Target's extension of semihosting user commands.
int64_t result
The current semihosting result to be returned to the application.
char * basedir
Base directory for semihosting I/O operations.
bool is_active
A flag reporting whether semihosting is active.
int op
The current semihosting operation (R0 on ARM).
struct connection * tcp_connection
Handle to redirect semihosting print via tcp.
int sys_errno
The value to be returned by semihosting SYS_ERRNO request.
enum semihosting_redirect_config redirect_cfg
redirection configuration, NONE by default
uint64_t param
The current semihosting parameter (R1 or ARM).
char * cmdline
The semihosting command line to be passed to the target.
clock_t setup_time
The current time when 'execution starts'.
const char * name
the name of the server
Definition: server.h:49
Definition: server.h:67
void * priv
Definition: server.h:81
char * name
Definition: server.h:68
char * port
Definition: server.h:70
int(* gdb_fileio_end)(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
Definition: target_type.h:283
int(* get_gdb_fileio_info)(struct target *target, struct gdb_fileio_info *fileio_info)
Definition: target_type.h:279
Definition: target.h:119
struct semihosting * semihosting
Definition: target.h:212
struct gdb_fileio_info * fileio_info
Definition: target.h:205
struct target_type * type
Definition: target.h:120
uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
Definition: target.c:316
int target_call_event_callbacks(struct target *target, enum target_event event)
Definition: target.c:1774
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
Definition: target.c:361
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2351
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2416
int target_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
Write count items of size bytes to the memory of target at the address given.
Definition: target.c:1275
void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value)
Definition: target.c:352
int target_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
Read count items of size bytes from the memory of target at the address given.
Definition: target.c:1247
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:467
void target_handle_event(struct target *target, enum target_event e)
Definition: target.c:4664
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
Definition: target.c:325
static bool target_was_examined(const struct target *target)
Definition: target.h:432
@ TARGET_EVENT_HALTED
Definition: target.h:255
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:236
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t count[4]
Definition: vdebug.c:22