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