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 
403  case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
404  /*
405  * Returns the number of centiseconds (hundredths of a second)
406  * since the execution started.
407  *
408  * Values returned can be of limited use for some benchmarking
409  * purposes because of communication overhead or other
410  * agent-specific factors. For example, with a debug hardware
411  * unit the request is passed back to the host for execution.
412  * This can lead to unpredictable delays in transmission and
413  * process scheduling.
414  *
415  * Use this function to calculate time intervals, by calculating
416  * differences between intervals with and without the code
417  * sequence to be timed.
418  *
419  * Entry
420  * The PARAMETER REGISTER must contain 0. There are no other
421  * parameters.
422  *
423  * Return
424  * On exit, the RETURN REGISTER contains:
425  * - The number of centiseconds since some arbitrary start
426  * point, if the call is successful.
427  * - –1 if the call is not successful. For example, because
428  * of a communications error.
429  */
430  {
431  clock_t delta = clock() - semihosting->setup_time;
432 
433  semihosting->result = delta / (CLOCKS_PER_SEC / 100);
434  }
435  break;
436 
437  case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
438  /*
439  * Closes a file on the host system. The handle must reference
440  * a file that was opened with SYS_OPEN.
441  *
442  * Entry
443  * On entry, the PARAMETER REGISTER contains a pointer to a
444  * one-field argument block:
445  * - field 1 Contains a handle for an open file.
446  *
447  * Return
448  * On exit, the RETURN REGISTER contains:
449  * - 0 if the call is successful
450  * - –1 if the call is not successful.
451  */
452  retval = semihosting_read_fields(target, 1, fields);
453  if (retval != ERROR_OK)
454  return retval;
455  else {
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  else {
558  int type = semihosting_get_field(target, 0, fields);
559  int code = semihosting_get_field(target, 1, fields);
560 
563  exit(code);
564  else {
565  fprintf(stderr,
566  "semihosting: *** application exited with %d ***\n",
567  code);
568  }
569  } else {
570  fprintf(stderr,
571  "semihosting: application exception %#x\n",
572  type);
573  }
574  }
575  } else {
578  exit(0);
579  else {
580  fprintf(stderr,
581  "semihosting: *** application exited normally ***\n");
582  }
584  /* Chosen more or less arbitrarily to have a nicer message,
585  * otherwise all other return the same exit code 1. */
587  exit(1);
588  else {
589  fprintf(stderr,
590  "semihosting: *** application exited with error ***\n");
591  }
592  } else {
594  exit(1);
595  else {
596  fprintf(stderr,
597  "semihosting: application exception %#x\n",
598  (unsigned) semihosting->param);
599  }
600  }
601  }
603  semihosting->is_resumable = false;
605  }
606  break;
607 
608  case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
609  /*
610  * This operation is only supported if the semihosting extension
611  * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
612  * reported using feature byte 0, bit 0. If this extension is
613  * supported, then the implementation provides a means to
614  * report a normal exit with a nonzero exit status in both 32-bit
615  * and 64-bit semihosting APIs.
616  *
617  * The implementation must provide the semihosting call
618  * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
619  *
620  * SYS_EXIT_EXTENDED is used by an application to report an
621  * exception or exit to the debugger directly. The most common
622  * use is to report that execution has completed, using
623  * ADP_Stopped_ApplicationExit.
624  *
625  * Entry
626  * On entry, the PARAMETER REGISTER contains a pointer to a
627  * two-field argument block:
628  * - field 1 The exception type, which should be one of the set
629  * of reason codes that are documented for the SYS_EXIT
630  * (0x18) call. For example, ADP_Stopped_ApplicationExit.
631  * - field 2 A subcode, whose meaning depends on the reason
632  * code in field 1. In particular, if field 1 is
633  * ADP_Stopped_ApplicationExit then field 2 is an exit status
634  * code, as passed to the C standard library exit() function.
635  * A simulator receiving this request must notify a connected
636  * debugger, if present, and then exit with the specified status.
637  *
638  * Return
639  * No return is expected from these calls.
640  *
641  * For the A64 API, this call is identical to the behavior of
642  * the mandatory SYS_EXIT (0x18) call. If this extension is
643  * supported, then both calls must be implemented.
644  */
645  retval = semihosting_read_fields(target, 2, fields);
646  if (retval != ERROR_OK)
647  return retval;
648  else {
649  int type = semihosting_get_field(target, 0, fields);
650  int code = semihosting_get_field(target, 1, fields);
651 
654  exit(code);
655  else {
656  fprintf(stderr,
657  "semihosting: *** application exited with %d ***\n",
658  code);
659  }
660  } else {
661  fprintf(stderr, "semihosting: exception %#x\n",
662  type);
663  }
664  }
666  semihosting->is_resumable = false;
668  }
669  break;
670 
671  case SEMIHOSTING_SYS_FLEN: /* 0x0C */
672  /*
673  * Returns the length of a specified file.
674  *
675  * Entry
676  * On entry, the PARAMETER REGISTER contains a pointer to a
677  * one-field argument block:
678  * - field 1 A handle for a previously opened, seekable file
679  * object.
680  *
681  * Return
682  * On exit, the RETURN REGISTER contains:
683  * - The current length of the file object, if the call is
684  * successful.
685  * - –1 if an error occurs.
686  */
687  if (semihosting->is_fileio) {
688  semihosting->result = -1;
689  semihosting->sys_errno = EINVAL;
690  }
691  retval = semihosting_read_fields(target, 1, fields);
692  if (retval != ERROR_OK)
693  return retval;
694  else {
695  int fd = semihosting_get_field(target, 0, fields);
696  struct stat buf;
697  semihosting->result = fstat(fd, &buf);
698  if (semihosting->result == -1) {
699  semihosting->sys_errno = errno;
700  LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
701  break;
702  }
703  LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
704  semihosting->result = buf.st_size;
705  }
706  break;
707 
708  case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
709  /*
710  * Returns the command line that is used for the call to the
711  * executable, that is, argc and argv.
712  *
713  * Entry
714  * On entry, the PARAMETER REGISTER points to a two-field data
715  * block to be used for returning the command string and its length:
716  * - field 1 A pointer to a buffer of at least the size that is
717  * specified in field 2.
718  * - field 2 The length of the buffer in bytes.
719  *
720  * Return
721  * On exit:
722  * If the call is successful, then the RETURN REGISTER contains 0,
723  * the PARAMETER REGISTER is unchanged, and the data block is
724  * updated as follows:
725  * - field 1 A pointer to a null-terminated string of the command
726  * line.
727  * - field 2 The length of the string in bytes.
728  * If the call is not successful, then the RETURN REGISTER
729  * contains -1.
730  *
731  * Note: The semihosting implementation might impose limits on
732  * the maximum length of the string that can be transferred.
733  * However, the implementation must be able to support a
734  * command-line length of at least 80 bytes.
735  */
736  retval = semihosting_read_fields(target, 2, fields);
737  if (retval != ERROR_OK)
738  return retval;
739  else {
740  uint64_t addr = semihosting_get_field(target, 0, fields);
741  size_t size = semihosting_get_field(target, 1, fields);
742 
743  char *arg = semihosting->cmdline ?
744  semihosting->cmdline : "";
745  uint32_t len = strlen(arg) + 1;
746  if (len > size)
747  semihosting->result = -1;
748  else {
749  semihosting_set_field(target, len, 1, fields);
750  retval = target_write_buffer(target, addr, len,
751  (uint8_t *)arg);
752  if (retval != ERROR_OK)
753  return retval;
754  semihosting->result = 0;
755 
756  retval = semihosting_write_fields(target, 2, fields);
757  if (retval != ERROR_OK)
758  return retval;
759  }
760  LOG_DEBUG("SYS_GET_CMDLINE=[%s], %" PRId64, arg, semihosting->result);
761  }
762  break;
763 
764  case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
765  /*
766  * Returns the system stack and heap parameters.
767  *
768  * Entry
769  * On entry, the PARAMETER REGISTER contains the address of a
770  * pointer to a four-field data block. The contents of the data
771  * block are filled by the function. The following C-like
772  * pseudocode describes the layout of the block:
773  * struct block {
774  * void* heap_base;
775  * void* heap_limit;
776  * void* stack_base;
777  * void* stack_limit;
778  * };
779  *
780  * Return
781  * On exit, the PARAMETER REGISTER is unchanged and the data
782  * block has been updated.
783  */
784  retval = semihosting_read_fields(target, 1, fields);
785  if (retval != ERROR_OK)
786  return retval;
787  else {
788  uint64_t addr = semihosting_get_field(target, 0, fields);
789  /* tell the remote we have no idea */
790  memset(fields, 0, 4 * semihosting->word_size_bytes);
791  retval = target_write_memory(target, addr, 4,
793  fields);
794  if (retval != ERROR_OK)
795  return retval;
796  semihosting->result = 0;
797  }
798  break;
799 
800  case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
801  /*
802  * Determines whether the return code from another semihosting
803  * call is an error status or not.
804  *
805  * This call is passed a parameter block containing the error
806  * code to examine.
807  *
808  * Entry
809  * On entry, the PARAMETER REGISTER contains a pointer to a
810  * one-field data block:
811  * - field 1 The required status word to check.
812  *
813  * Return
814  * On exit, the RETURN REGISTER contains:
815  * - 0 if the status field is not an error indication
816  * - A nonzero value if the status field is an error indication.
817  */
818  retval = semihosting_read_fields(target, 1, fields);
819  if (retval != ERROR_OK)
820  return retval;
821 
822  uint64_t code = semihosting_get_field(target, 0, fields);
823  semihosting->result = (code != 0);
824  break;
825 
826  case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
827  /*
828  * Checks whether a file is connected to an interactive device.
829  *
830  * Entry
831  * On entry, the PARAMETER REGISTER contains a pointer to a
832  * one-field argument block:
833  * field 1 A handle for a previously opened file object.
834  *
835  * Return
836  * On exit, the RETURN REGISTER contains:
837  * - 1 if the handle identifies an interactive device.
838  * - 0 if the handle identifies a file.
839  * - A value other than 1 or 0 if an error occurs.
840  */
841  if (semihosting->is_fileio) {
842  semihosting->hit_fileio = true;
843  fileio_info->identifier = "isatty";
844  fileio_info->param_1 = semihosting->param;
845  } else {
846  retval = semihosting_read_fields(target, 1, fields);
847  if (retval != ERROR_OK)
848  return retval;
849  int fd = semihosting_get_field(target, 0, fields);
850  // isatty() on Windows may return any non-zero value if fd is a terminal
851  semihosting->result = isatty(fd) ? 1 : 0;
852  if (semihosting->result == 0)
853  semihosting->sys_errno = errno;
854  LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result);
855  }
856  break;
857 
858  case SEMIHOSTING_SYS_OPEN: /* 0x01 */
859  /*
860  * Opens a file on the host system.
861  *
862  * The file path is specified either as relative to the current
863  * directory of the host process, or absolute, using the path
864  * conventions of the host operating system.
865  *
866  * Semihosting implementations must support opening the special
867  * path name :semihosting-features as part of the semihosting
868  * extensions reporting mechanism.
869  *
870  * ARM targets interpret the special path name :tt as meaning
871  * the console input stream, for an open-read or the console
872  * output stream, for an open-write. Opening these streams is
873  * performed as part of the standard startup code for those
874  * applications that reference the C stdio streams. The
875  * semihosting extension SH_EXT_STDOUT_STDERR allows the
876  * semihosting caller to open separate output streams
877  * corresponding to stdout and stderr. This extension is
878  * reported using feature byte 0, bit 1. Use SYS_OPEN with
879  * the special path name :semihosting-features to access the
880  * feature bits.
881  *
882  * If this extension is supported, the implementation must
883  * support the following additional semantics to SYS_OPEN:
884  * - If the special path name :tt is opened with an fopen
885  * mode requesting write access (w, wb, w+, or w+b), then
886  * this is a request to open stdout.
887  * - If the special path name :tt is opened with a mode
888  * requesting append access (a, ab, a+, or a+b), then this is
889  * a request to open stderr.
890  *
891  * Entry
892  * On entry, the PARAMETER REGISTER contains a pointer to a
893  * three-field argument block:
894  * - field 1 A pointer to a null-terminated string containing
895  * a file or device name.
896  * - field 2 An integer that specifies the file opening mode.
897  * - field 3 An integer that gives the length of the string
898  * pointed to by field 1.
899  *
900  * The length does not include the terminating null character
901  * that must be present.
902  *
903  * Return
904  * On exit, the RETURN REGISTER contains:
905  * - A nonzero handle if the call is successful.
906  * - –1 if the call is not successful.
907  */
908  retval = semihosting_read_fields(target, 3, fields);
909  if (retval != ERROR_OK)
910  return retval;
911  else {
912  uint64_t addr = semihosting_get_field(target, 0, fields);
913  uint32_t mode = semihosting_get_field(target, 1, fields);
914  size_t len = semihosting_get_field(target, 2, fields);
915 
916  if (mode > 11) {
917  semihosting->result = -1;
918  semihosting->sys_errno = EINVAL;
919  break;
920  }
921  size_t basedir_len = semihosting->basedir ? strlen(semihosting->basedir) : 0;
922  uint8_t *fn = malloc(basedir_len + len + 2);
923  if (!fn) {
924  semihosting->result = -1;
925  semihosting->sys_errno = ENOMEM;
926  } else {
927  if (basedir_len > 0) {
928  strcpy((char *)fn, semihosting->basedir);
929  if (fn[basedir_len - 1] != '/')
930  fn[basedir_len++] = '/';
931  }
932  retval = target_read_memory(target, addr, 1, len, fn + basedir_len);
933  if (retval != ERROR_OK) {
934  free(fn);
935  return retval;
936  }
937  fn[basedir_len + len] = 0;
938  /* TODO: implement the :semihosting-features special file.
939  * */
940  if (semihosting->is_fileio) {
941  if (strcmp((char *)fn, ":semihosting-features") == 0) {
942  semihosting->result = -1;
943  semihosting->sys_errno = EINVAL;
944  } else if (strcmp((char *)fn, ":tt") == 0) {
945  if (mode == 0) {
946  semihosting->result = 0;
947  } else if (mode == 4) {
948  semihosting->result = 1;
949  } else if (mode == 8) {
950  semihosting->result = 2;
951  } else {
952  semihosting->result = -1;
953  semihosting->sys_errno = EINVAL;
954  }
955  } else {
956  semihosting->hit_fileio = true;
957  fileio_info->identifier = "open";
958  fileio_info->param_1 = addr;
959  fileio_info->param_2 = len;
960  fileio_info->param_3 = open_gdb_modeflags[mode];
961  fileio_info->param_4 = 0644;
962  }
963  } else {
964  if (strcmp((char *)fn, ":tt") == 0) {
965  /* Mode is:
966  * - 0-3 ("r") for stdin,
967  * - 4-7 ("w") for stdout,
968  * - 8-11 ("a") for stderr */
969  int fd;
970  if (mode < 4) {
971  fd = dup(STDIN_FILENO);
972  semihosting->stdin_fd = fd;
973  LOG_DEBUG("dup(STDIN)=%d", fd);
974  } else if (mode < 8) {
975  fd = dup(STDOUT_FILENO);
976  semihosting->stdout_fd = fd;
977  LOG_DEBUG("dup(STDOUT)=%d", fd);
978  } else {
979  fd = dup(STDERR_FILENO);
980  semihosting->stderr_fd = fd;
981  LOG_DEBUG("dup(STDERR)=%d", fd);
982  }
983  semihosting->result = fd;
984  if (fd == -1)
985  semihosting->sys_errno = errno;
986  } else {
987  /* cygwin requires the permission setting
988  * otherwise it will fail to reopen a previously
989  * written file */
990  semihosting->result = open((char *)fn,
992  0644);
993  if (semihosting->result == -1)
994  semihosting->sys_errno = errno;
995  LOG_DEBUG("open('%s')=%" PRId64, fn, semihosting->result);
996  }
997  }
998  free(fn);
999  }
1000  }
1001  break;
1002 
1003  case SEMIHOSTING_SYS_READ: /* 0x06 */
1004  /*
1005  * Reads the contents of a file into a buffer. The file position
1006  * is specified either:
1007  * - Explicitly by a SYS_SEEK.
1008  * - Implicitly one byte beyond the previous SYS_READ or
1009  * SYS_WRITE request.
1010  *
1011  * The file position is at the start of the file when it is
1012  * opened, and is lost when the file is closed. Perform the
1013  * file operation as a single action whenever possible. For
1014  * example, do not split a read of 16KB into four 4KB chunks
1015  * unless there is no alternative.
1016  *
1017  * Entry
1018  * On entry, the PARAMETER REGISTER contains a pointer to a
1019  * three-field data block:
1020  * - field 1 Contains a handle for a file previously opened
1021  * with SYS_OPEN.
1022  * - field 2 Points to a buffer.
1023  * - field 3 Contains the number of bytes to read to the buffer
1024  * from the file.
1025  *
1026  * Return
1027  * On exit, the RETURN REGISTER contains the number of bytes not
1028  * filled in the buffer (buffer_length - bytes_read) as follows:
1029  * - If the RETURN REGISTER is 0, the entire buffer was
1030  * successfully filled.
1031  * - If the RETURN REGISTER is the same as field 3, no bytes
1032  * were read (EOF can be assumed).
1033  * - If the RETURN REGISTER contains a value smaller than
1034  * field 3, the read succeeded but the buffer was only partly
1035  * filled. For interactive devices, this is the most common
1036  * return value.
1037  */
1038  retval = semihosting_read_fields(target, 3, fields);
1039  if (retval != ERROR_OK)
1040  return retval;
1041  else {
1042  int fd = semihosting_get_field(target, 0, fields);
1043  uint64_t addr = semihosting_get_field(target, 1, fields);
1044  size_t len = semihosting_get_field(target, 2, fields);
1045  if (semihosting->is_fileio) {
1046  semihosting->hit_fileio = true;
1047  fileio_info->identifier = "read";
1048  fileio_info->param_1 = fd;
1049  fileio_info->param_2 = addr;
1050  fileio_info->param_3 = len;
1051  } else {
1052  uint8_t *buf = malloc(len);
1053  if (!buf) {
1054  semihosting->result = -1;
1055  semihosting->sys_errno = ENOMEM;
1056  } else {
1057  semihosting->result = semihosting_read(semihosting, fd, buf, len);
1058  LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1059  fd,
1060  addr,
1061  len,
1062  semihosting->result);
1063  if (semihosting->result >= 0) {
1064  retval = target_write_buffer(target, addr,
1066  buf);
1067  if (retval != ERROR_OK) {
1068  free(buf);
1069  return retval;
1070  }
1071  /* the number of bytes NOT filled in */
1072  semihosting->result = len -
1074  }
1075  free(buf);
1076  }
1077  }
1078  }
1079  break;
1080 
1081  case SEMIHOSTING_SYS_READC: /* 0x07 */
1082  /*
1083  * Reads a byte from the console.
1084  *
1085  * Entry
1086  * The PARAMETER REGISTER must contain 0. There are no other
1087  * parameters or values possible.
1088  *
1089  * Return
1090  * On exit, the RETURN REGISTER contains the byte read from
1091  * the console.
1092  */
1093  if (semihosting->is_fileio) {
1094  LOG_ERROR("SYS_READC not supported by semihosting fileio");
1095  return ERROR_FAIL;
1096  }
1098  LOG_DEBUG("getchar()=%" PRId64, semihosting->result);
1099  break;
1100 
1101  case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
1102  /*
1103  * Deletes a specified file on the host filing system.
1104  *
1105  * Entry
1106  * On entry, the PARAMETER REGISTER contains a pointer to a
1107  * two-field argument block:
1108  * - field 1 Points to a null-terminated string that gives the
1109  * path name of the file to be deleted.
1110  * - field 2 The length of the string.
1111  *
1112  * Return
1113  * On exit, the RETURN REGISTER contains:
1114  * - 0 if the delete is successful
1115  * - A nonzero, host-specific error code if the delete fails.
1116  */
1117  retval = semihosting_read_fields(target, 2, fields);
1118  if (retval != ERROR_OK)
1119  return retval;
1120  else {
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 =
1135  target_read_memory(target, addr, 1, len,
1136  fn);
1137  if (retval != ERROR_OK) {
1138  free(fn);
1139  return retval;
1140  }
1141  fn[len] = 0;
1142  semihosting->result = remove((char *)fn);
1143  if (semihosting->result == -1)
1144  semihosting->sys_errno = errno;
1145  LOG_DEBUG("remove('%s')=%" PRId64, fn, semihosting->result);
1146 
1147  free(fn);
1148  }
1149  }
1150  }
1151  break;
1152 
1153  case SEMIHOSTING_SYS_RENAME: /* 0x0F */
1154  /*
1155  * Renames a specified file.
1156  *
1157  * Entry
1158  * On entry, the PARAMETER REGISTER contains a pointer to a
1159  * four-field data block:
1160  * - field 1 A pointer to the name of the old file.
1161  * - field 2 The length of the old filename.
1162  * - field 3 A pointer to the new filename.
1163  * - field 4 The length of the new filename. Both strings are
1164  * null-terminated.
1165  *
1166  * Return
1167  * On exit, the RETURN REGISTER contains:
1168  * - 0 if the rename is successful.
1169  * - A nonzero, host-specific error code if the rename fails.
1170  */
1171  retval = semihosting_read_fields(target, 4, fields);
1172  if (retval != ERROR_OK)
1173  return retval;
1174  else {
1175  uint64_t addr1 = semihosting_get_field(target, 0, fields);
1176  size_t len1 = semihosting_get_field(target, 1, fields);
1177  uint64_t addr2 = semihosting_get_field(target, 2, fields);
1178  size_t len2 = semihosting_get_field(target, 3, fields);
1179  if (semihosting->is_fileio) {
1180  semihosting->hit_fileio = true;
1181  fileio_info->identifier = "rename";
1182  fileio_info->param_1 = addr1;
1183  fileio_info->param_2 = len1;
1184  fileio_info->param_3 = addr2;
1185  fileio_info->param_4 = len2;
1186  } else {
1187  uint8_t *fn1 = malloc(len1+1);
1188  uint8_t *fn2 = malloc(len2+1);
1189  if (!fn1 || !fn2) {
1190  free(fn1);
1191  free(fn2);
1192  semihosting->result = -1;
1193  semihosting->sys_errno = ENOMEM;
1194  } else {
1195  retval = target_read_memory(target, addr1, 1, len1,
1196  fn1);
1197  if (retval != ERROR_OK) {
1198  free(fn1);
1199  free(fn2);
1200  return retval;
1201  }
1202  retval = target_read_memory(target, addr2, 1, len2,
1203  fn2);
1204  if (retval != ERROR_OK) {
1205  free(fn1);
1206  free(fn2);
1207  return retval;
1208  }
1209  fn1[len1] = 0;
1210  fn2[len2] = 0;
1211  semihosting->result = rename((char *)fn1,
1212  (char *)fn2);
1213  // rename() on Windows returns nonzero on error
1214  if (semihosting->result != 0)
1215  semihosting->sys_errno = errno;
1216  LOG_DEBUG("rename('%s', '%s')=%" PRId64 " %d", fn1, fn2, semihosting->result, errno);
1217  free(fn1);
1218  free(fn2);
1219  }
1220  }
1221  }
1222  break;
1223 
1224  case SEMIHOSTING_SYS_SEEK: /* 0x0A */
1225  /*
1226  * Seeks to a specified position in a file using an offset
1227  * specified from the start of the file. The file is assumed
1228  * to be a byte array and the offset is given in bytes.
1229  *
1230  * Entry
1231  * On entry, the PARAMETER REGISTER contains a pointer to a
1232  * two-field data block:
1233  * - field 1 A handle for a seekable file object.
1234  * - field 2 The absolute byte position to seek to.
1235  *
1236  * Return
1237  * On exit, the RETURN REGISTER contains:
1238  * - 0 if the request is successful.
1239  * - A negative value if the request is not successful.
1240  * Use SYS_ERRNO to read the value of the host errno variable
1241  * describing the error.
1242  *
1243  * Note: The effect of seeking outside the current extent of
1244  * the file object is undefined.
1245  */
1246  retval = semihosting_read_fields(target, 2, fields);
1247  if (retval != ERROR_OK)
1248  return retval;
1249  else {
1250  int fd = semihosting_get_field(target, 0, fields);
1251  off_t pos = semihosting_get_field(target, 1, fields);
1252  if (semihosting->is_fileio) {
1253  semihosting->hit_fileio = true;
1254  fileio_info->identifier = "lseek";
1255  fileio_info->param_1 = fd;
1256  fileio_info->param_2 = pos;
1257  fileio_info->param_3 = SEEK_SET;
1258  } else {
1259  semihosting->result = lseek(fd, pos, SEEK_SET);
1260  if (semihosting->result == -1)
1261  semihosting->sys_errno = errno;
1262  LOG_DEBUG("lseek(%d, %d)=%" PRId64, fd, (int)pos, semihosting->result);
1263  if (semihosting->result == pos)
1264  semihosting->result = 0;
1265  }
1266  }
1267  break;
1268 
1269  case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1270  /*
1271  * Passes a command to the host command-line interpreter.
1272  * This enables you to execute a system command such as dir,
1273  * ls, or pwd. The terminal I/O is on the host, and is not
1274  * visible to the target.
1275  *
1276  * Entry
1277  * On entry, the PARAMETER REGISTER contains a pointer to a
1278  * two-field argument block:
1279  * - field 1 Points to a string to be passed to the host
1280  * command-line interpreter.
1281  * - field 2 The length of the string.
1282  *
1283  * Return
1284  * On exit, the RETURN REGISTER contains the return status.
1285  */
1286 
1287  /* Provide SYS_SYSTEM functionality. Uses the
1288  * libc system command, there may be a reason *NOT*
1289  * to use this, but as I can't think of one, I
1290  * implemented it this way.
1291  */
1292  retval = semihosting_read_fields(target, 2, fields);
1293  if (retval != ERROR_OK)
1294  return retval;
1295  else {
1296  uint64_t addr = semihosting_get_field(target, 0, fields);
1297  size_t len = semihosting_get_field(target, 1, fields);
1298  if (semihosting->is_fileio) {
1299  semihosting->hit_fileio = true;
1300  fileio_info->identifier = "system";
1301  fileio_info->param_1 = addr;
1302  fileio_info->param_2 = len;
1303  } else {
1304  uint8_t *cmd = malloc(len+1);
1305  if (!cmd) {
1306  semihosting->result = -1;
1307  semihosting->sys_errno = ENOMEM;
1308  } else {
1309  retval = target_read_memory(target,
1310  addr,
1311  1,
1312  len,
1313  cmd);
1314  if (retval != ERROR_OK) {
1315  free(cmd);
1316  return retval;
1317  } else {
1318  cmd[len] = 0;
1319  semihosting->result = system(
1320  (const char *)cmd);
1321  LOG_DEBUG("system('%s')=%" PRId64, cmd, semihosting->result);
1322  }
1323 
1324  free(cmd);
1325  }
1326  }
1327  }
1328  break;
1329 
1330  case SEMIHOSTING_SYS_TIME: /* 0x11 */
1331  /*
1332  * Returns the number of seconds since 00:00 January 1, 1970.
1333  * This value is real-world time, regardless of any debug agent
1334  * configuration.
1335  *
1336  * Entry
1337  * There are no parameters.
1338  *
1339  * Return
1340  * On exit, the RETURN REGISTER contains the number of seconds.
1341  */
1342  semihosting->result = time(NULL);
1343  break;
1344 
1345  case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1346  /*
1347  * Writes the contents of a buffer to a specified file at the
1348  * current file position. The file position is specified either:
1349  * - Explicitly, by a SYS_SEEK.
1350  * - Implicitly as one byte beyond the previous SYS_READ or
1351  * SYS_WRITE request.
1352  *
1353  * The file position is at the start of the file when the file
1354  * is opened, and is lost when the file is closed.
1355  *
1356  * Perform the file operation as a single action whenever
1357  * possible. For example, do not split a write of 16KB into
1358  * four 4KB chunks unless there is no alternative.
1359  *
1360  * Entry
1361  * On entry, the PARAMETER REGISTER contains a pointer to a
1362  * three-field data block:
1363  * - field 1 Contains a handle for a file previously opened
1364  * with SYS_OPEN.
1365  * - field 2 Points to the memory containing the data to be written.
1366  * - field 3 Contains the number of bytes to be written from
1367  * the buffer to the file.
1368  *
1369  * Return
1370  * On exit, the RETURN REGISTER contains:
1371  * - 0 if the call is successful.
1372  * - The number of bytes that are not written, if there is an error.
1373  */
1374  retval = semihosting_read_fields(target, 3, fields);
1375  if (retval != ERROR_OK)
1376  return retval;
1377  else {
1378  int fd = semihosting_get_field(target, 0, fields);
1379  uint64_t addr = semihosting_get_field(target, 1, fields);
1380  size_t len = semihosting_get_field(target, 2, fields);
1381  if (semihosting->is_fileio) {
1382  semihosting->hit_fileio = true;
1383  fileio_info->identifier = "write";
1384  fileio_info->param_1 = fd;
1385  fileio_info->param_2 = addr;
1386  fileio_info->param_3 = len;
1387  } else {
1388  uint8_t *buf = malloc(len);
1389  if (!buf) {
1390  semihosting->result = -1;
1391  semihosting->sys_errno = ENOMEM;
1392  } else {
1393  retval = target_read_buffer(target, addr, len, buf);
1394  if (retval != ERROR_OK) {
1395  free(buf);
1396  return retval;
1397  }
1398  semihosting->result = semihosting_write(semihosting, fd, buf, len);
1399  LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1400  fd,
1401  addr,
1402  len,
1403  semihosting->result);
1404  if (semihosting->result >= 0) {
1405  /* The number of bytes that are NOT written.
1406  * */
1407  semihosting->result = len -
1409  }
1410 
1411  free(buf);
1412  }
1413  }
1414  }
1415  break;
1416 
1417  case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1418  /*
1419  * Writes a character byte, pointed to by the PARAMETER REGISTER,
1420  * to the debug channel. When executed under a semihosting
1421  * debugger, the character appears on the host debugger console.
1422  *
1423  * Entry
1424  * On entry, the PARAMETER REGISTER contains a pointer to the
1425  * character.
1426  *
1427  * Return
1428  * None. The RETURN REGISTER is corrupted.
1429  */
1430  if (semihosting->is_fileio) {
1431  semihosting->hit_fileio = true;
1432  fileio_info->identifier = "write";
1433  fileio_info->param_1 = 1;
1434  fileio_info->param_2 = semihosting->param;
1435  fileio_info->param_3 = 1;
1436  } else {
1437  uint64_t addr = semihosting->param;
1438  unsigned char c;
1439  retval = target_read_memory(target, addr, 1, 1, &c);
1440  if (retval != ERROR_OK)
1441  return retval;
1443  semihosting->result = 0;
1444  }
1445  break;
1446 
1447  case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1448  /*
1449  * Writes a null-terminated string to the debug channel.
1450  * When executed under a semihosting debugger, the characters
1451  * appear on the host debugger console.
1452  *
1453  * Entry
1454  * On entry, the PARAMETER REGISTER contains a pointer to the
1455  * first byte of the string.
1456  *
1457  * Return
1458  * None. The RETURN REGISTER is corrupted.
1459  */
1460  if (semihosting->is_fileio) {
1461  size_t count = 0;
1462  uint64_t addr = semihosting->param;
1463  for (;; addr++) {
1464  unsigned char c;
1465  retval = target_read_memory(target, addr, 1, 1, &c);
1466  if (retval != ERROR_OK)
1467  return retval;
1468  if (c == '\0')
1469  break;
1470  count++;
1471  }
1472  semihosting->hit_fileio = true;
1473  fileio_info->identifier = "write";
1474  fileio_info->param_1 = 1;
1475  fileio_info->param_2 = semihosting->param;
1476  fileio_info->param_3 = count;
1477  } else {
1478  uint64_t addr = semihosting->param;
1479  do {
1480  unsigned char c;
1481  retval = target_read_memory(target, addr++, 1, 1, &c);
1482  if (retval != ERROR_OK)
1483  return retval;
1484  if (!c)
1485  break;
1487  } while (1);
1488  semihosting->result = 0;
1489  }
1490  break;
1491 
1513  if (retval != ERROR_NOT_IMPLEMENTED)
1514  break;
1515  /* If custom user command not handled, we are looking for the TCL handler */
1516  }
1517 
1518  assert(!semihosting_user_op_params);
1519  retval = semihosting_read_fields(target, 2, fields);
1520  if (retval != ERROR_OK) {
1521  LOG_ERROR("Failed to read fields for user defined command"
1522  " op=0x%x", semihosting->op);
1523  return retval;
1524  }
1525 
1526  uint64_t addr = semihosting_get_field(target, 0, fields);
1527 
1528  size_t len = semihosting_get_field(target, 1, fields);
1530  LOG_ERROR("The maximum length for user defined command "
1531  "parameter is %u, received length is %zu (op=0x%x)",
1533  len,
1534  semihosting->op);
1535  return ERROR_FAIL;
1536  }
1537 
1538  semihosting_user_op_params = malloc(len + 1);
1540  return ERROR_FAIL;
1541  semihosting_user_op_params[len] = 0;
1542 
1543  retval = target_read_buffer(target, addr, len,
1544  (uint8_t *)(semihosting_user_op_params));
1545  if (retval != ERROR_OK) {
1546  LOG_ERROR("Failed to read from target, semihosting op=0x%x (%s)",
1547  semihosting->op,
1551  return retval;
1552  }
1553 
1557  semihosting->result = 0;
1558  break;
1559 
1560  case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1561  /*
1562  * Returns the number of elapsed target ticks since execution
1563  * started.
1564  * Use SYS_TICKFREQ to determine the tick frequency.
1565  *
1566  * Entry (32-bit)
1567  * On entry, the PARAMETER REGISTER points to a two-field data
1568  * block to be used for returning the number of elapsed ticks:
1569  * - field 1 The least significant field and is at the low address.
1570  * - field 2 The most significant field and is at the high address.
1571  *
1572  * Entry (64-bit)
1573  * On entry the PARAMETER REGISTER points to a one-field data
1574  * block to be used for returning the number of elapsed ticks:
1575  * - field 1 The number of elapsed ticks as a 64-bit value.
1576  *
1577  * Return
1578  * On exit:
1579  * - On success, the RETURN REGISTER contains 0, the PARAMETER
1580  * REGISTER is unchanged, and the data block pointed to by the
1581  * PARAMETER REGISTER is filled in with the number of elapsed
1582  * ticks.
1583  * - On failure, the RETURN REGISTER contains -1, and the
1584  * PARAMETER REGISTER contains -1.
1585  *
1586  * Note: Some semihosting implementations might not support this
1587  * semihosting operation, and they always return -1 in the
1588  * RETURN REGISTER.
1589  */
1590 
1591  case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1592  /*
1593  * Returns the tick frequency.
1594  *
1595  * Entry
1596  * The PARAMETER REGISTER must contain 0 on entry to this routine.
1597  *
1598  * Return
1599  * On exit, the RETURN REGISTER contains either:
1600  * - The number of ticks per second.
1601  * - –1 if the target does not know the value of one tick.
1602  *
1603  * Note: Some semihosting implementations might not support
1604  * this semihosting operation, and they always return -1 in the
1605  * RETURN REGISTER.
1606  */
1607 
1608  case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1609  /*
1610  * Returns a temporary name for a file identified by a system
1611  * file identifier.
1612  *
1613  * Entry
1614  * On entry, the PARAMETER REGISTER contains a pointer to a
1615  * three-word argument block:
1616  * - field 1 A pointer to a buffer.
1617  * - field 2 A target identifier for this filename. Its value
1618  * must be an integer in the range 0-255.
1619  * - field 3 Contains the length of the buffer. The length must
1620  * be at least the value of L_tmpnam on the host system.
1621  *
1622  * Return
1623  * On exit, the RETURN REGISTER contains:
1624  * - 0 if the call is successful.
1625  * - –1 if an error occurs.
1626  *
1627  * The buffer pointed to by the PARAMETER REGISTER contains
1628  * the filename, prefixed with a suitable directory name.
1629  * If you use the same target identifier again, the same
1630  * filename is returned.
1631  *
1632  * Note: The returned string must be null-terminated.
1633  */
1634 
1635  default:
1636  fprintf(stderr, "semihosting: unsupported call %#x\n",
1637  (unsigned) semihosting->op);
1638  semihosting->result = -1;
1640  }
1641 
1642  if (!semihosting->hit_fileio) {
1643  retval = semihosting->post_result(target);
1644  if (retval != ERROR_OK) {
1645  LOG_ERROR("Failed to post semihosting result");
1646  return retval;
1647  }
1648  }
1649 
1650  return ERROR_OK;
1651 }
1652 
1653 /* -------------------------------------------------------------------------
1654  * Local functions. */
1655 
1657  struct gdb_fileio_info *fileio_info)
1658 {
1660  if (!semihosting)
1661  return ERROR_FAIL;
1662 
1663  /*
1664  * To avoid unnecessary duplication, semihosting prepares the
1665  * fileio_info structure out-of-band when the target halts. See
1666  * do_semihosting for more detail.
1667  */
1669  return ERROR_FAIL;
1670 
1671  return ERROR_OK;
1672 }
1673 
1675  int fileio_errno, bool ctrl_c)
1676 {
1677  struct gdb_fileio_info *fileio_info = target->fileio_info;
1679  if (!semihosting)
1680  return ERROR_FAIL;
1681 
1682  /* clear pending status */
1683  semihosting->hit_fileio = false;
1684 
1686 
1687  /*
1688  * Some fileio results do not match up with what the semihosting
1689  * operation expects; for these operations, we munge the results
1690  * below:
1691  */
1692  switch (semihosting->op) {
1693  case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1694  case SEMIHOSTING_SYS_READ: /* 0x06 */
1695  if (result < 0)
1696  semihosting->result = fileio_info->param_3; /* Zero bytes read/written. */
1697  else
1698  semihosting->result = (int64_t)fileio_info->param_3 - result;
1699  break;
1700 
1701  case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1702  if (result > 0)
1703  semihosting->result = 0;
1704  break;
1705  }
1706 
1707  bool fileio_failed = false;
1709  fileio_failed = (semihosting->result == 0);
1710  else if (semihosting->op == SEMIHOSTING_SYS_RENAME)
1711  fileio_failed = (semihosting->result != 0);
1712  else
1713  fileio_failed = (semihosting->result == -1);
1714 
1715  if (fileio_failed)
1716  semihosting->sys_errno = fileio_errno;
1717 
1718  return semihosting->post_result(target);
1719 }
1720 
1721 /* -------------------------------------------------------------------------
1722  * Utility functions. */
1723 
1728  uint8_t *fields)
1729 {
1731  /* Use 4-byte multiples to trigger fast memory access. */
1733  number * (semihosting->word_size_bytes / 4), fields);
1734 }
1735 
1739 static int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields)
1740 {
1742  /* Use 4-byte multiples to trigger fast memory access. */
1744  number * (semihosting->word_size_bytes / 4), fields);
1745 }
1746 
1750 uint64_t semihosting_get_field(struct target *target, size_t index,
1751  uint8_t *fields)
1752 {
1754  if (semihosting->word_size_bytes == 8)
1755  return target_buffer_get_u64(target, fields + (index * 8));
1756  else
1757  return target_buffer_get_u32(target, fields + (index * 4));
1758 }
1759 
1763 static void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields)
1764 {
1766  if (semihosting->word_size_bytes == 8)
1767  target_buffer_set_u64(target, fields + (index * 8), value);
1768  else
1769  target_buffer_set_u32(target, fields + (index * 4), value);
1770 }
1771 
1772 /* -------------------------------------------------------------------------
1773  * Semihosting redirect over TCP structs and functions */
1774 
1776 {
1778  service->semihosting->tcp_connection = connection;
1779 
1780  return ERROR_OK;
1781 }
1782 
1784 {
1786 
1787  if (!connection->input_pending) {
1788  /* consume received data, not for semihosting IO */
1789  const int buf_len = 100;
1790  char buf[buf_len];
1791  int bytes_read = connection_read(connection, buf, buf_len);
1792 
1793  if (bytes_read == 0) {
1795  } else if (bytes_read == -1) {
1796  LOG_ERROR("error during read: %s", strerror(errno));
1798  }
1799  } else if (service->error != ERROR_OK) {
1801  }
1802 
1803  return ERROR_OK;
1804 }
1805 
1807 {
1809  if (service)
1810  free(service->name);
1811 
1812  return ERROR_OK;
1813 }
1814 
1816 {
1818  return;
1819 
1823 
1824 }
1825 
1826 static const struct service_driver semihosting_service_driver = {
1827  .name = "semihosting",
1828  .new_connection_during_keep_alive_handler = NULL,
1829  .new_connection_handler = semihosting_service_new_connection_handler,
1830  .input_handler = semihosting_service_input_handler,
1831  .connection_closed_handler = semihosting_service_connection_closed_handler,
1832  .keep_client_alive_handler = NULL,
1833 };
1834 
1835 /* -------------------------------------------------------------------------
1836  * Common semihosting commands handlers. */
1837 
1838 COMMAND_HANDLER(handle_common_semihosting_command)
1839 {
1841 
1842  if (!target) {
1843  LOG_ERROR("No target selected");
1844  return ERROR_FAIL;
1845  }
1846 
1848  if (!semihosting) {
1849  command_print(CMD, "semihosting not supported for current target");
1850  return ERROR_FAIL;
1851  }
1852 
1853  if (CMD_ARGC > 0) {
1854  int is_active;
1855 
1857 
1858  if (!target_was_examined(target)) {
1859  LOG_ERROR("Target not examined yet");
1860  return ERROR_FAIL;
1861  }
1862 
1864  LOG_ERROR("Failed to Configure semihosting");
1865  return ERROR_FAIL;
1866  }
1867 
1868  /* FIXME never let that "catch" be dropped! (???) */
1870  }
1871 
1872  command_print(CMD, "semihosting is %s",
1874  ? "enabled" : "disabled");
1875 
1876  return ERROR_OK;
1877 }
1878 
1879 COMMAND_HANDLER(handle_common_semihosting_redirect_command)
1880 {
1882 
1883  if (!target) {
1884  LOG_ERROR("No target selected");
1885  return ERROR_FAIL;
1886  }
1887 
1889  if (!semihosting) {
1890  command_print(CMD, "semihosting not supported for current target");
1891  return ERROR_FAIL;
1892  }
1893 
1894  if (!semihosting->is_active) {
1895  command_print(CMD, "semihosting not yet enabled for current target");
1896  return ERROR_FAIL;
1897  }
1898 
1899  enum semihosting_redirect_config cfg;
1900  const char *port;
1901 
1902  if (CMD_ARGC < 1)
1904 
1905  if (strcmp(CMD_ARGV[0], "disable") == 0) {
1907  if (CMD_ARGC > 1)
1909  } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
1910  if (CMD_ARGC < 2 || CMD_ARGC > 3)
1912 
1913  port = CMD_ARGV[1];
1914 
1916  if (CMD_ARGC == 3) {
1917  if (strcmp(CMD_ARGV[2], "debug") == 0)
1919  else if (strcmp(CMD_ARGV[2], "stdio") == 0)
1921  else if (strcmp(CMD_ARGV[2], "all") != 0)
1923  }
1924  } else {
1926  }
1927 
1930 
1931  if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) {
1933  calloc(1, sizeof(struct semihosting_tcp_service));
1934  if (!service) {
1935  LOG_ERROR("Failed to allocate semihosting TCP service.");
1936  return ERROR_FAIL;
1937  }
1938 
1939  service->semihosting = semihosting;
1940 
1941  service->name = alloc_printf("%s semihosting service", target_name(target));
1942  if (!service->name) {
1943  LOG_ERROR("Out of memory");
1944  free(service);
1945  return ERROR_FAIL;
1946  }
1947 
1949  port, 1, service);
1950 
1951  if (ret != ERROR_OK) {
1952  LOG_ERROR("failed to initialize %s", service->name);
1953  free(service->name);
1954  free(service);
1955  return ERROR_FAIL;
1956  }
1957  }
1958 
1959  semihosting->redirect_cfg = cfg;
1960 
1961  return ERROR_OK;
1962 }
1963 
1964 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1965 {
1967 
1968  if (!target) {
1969  LOG_ERROR("No target selected");
1970  return ERROR_FAIL;
1971  }
1972 
1974  if (!semihosting) {
1975  command_print(CMD, "semihosting not supported for current target");
1976  return ERROR_FAIL;
1977  }
1978 
1979  if (!semihosting->is_active) {
1980  command_print(CMD, "semihosting not yet enabled for current target");
1981  return ERROR_FAIL;
1982  }
1983 
1984  if (CMD_ARGC > 0)
1986 
1987  command_print(CMD, "semihosting fileio is %s",
1989  ? "enabled" : "disabled");
1990 
1991  return ERROR_OK;
1992 }
1993 
1994 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1995 {
1997  unsigned int i;
1998 
1999  if (!target) {
2000  LOG_ERROR("No target selected");
2001  return ERROR_FAIL;
2002  }
2003 
2005  if (!semihosting) {
2006  command_print(CMD, "semihosting not supported for current target");
2007  return ERROR_FAIL;
2008  }
2009 
2010  free(semihosting->cmdline);
2011  semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
2012 
2013  for (i = 1; i < CMD_ARGC; i++) {
2014  char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
2015  if (!cmdline)
2016  break;
2017  free(semihosting->cmdline);
2019  }
2020 
2021  command_print(CMD, "semihosting command line is [%s]",
2022  semihosting->cmdline);
2023 
2024  return ERROR_OK;
2025 }
2026 
2027 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
2028 {
2030 
2031  if (!target) {
2032  LOG_ERROR("No target selected");
2033  return ERROR_FAIL;
2034  }
2035 
2037  if (!semihosting) {
2038  command_print(CMD, "semihosting not supported for current target");
2039  return ERROR_FAIL;
2040  }
2041 
2042  if (!semihosting->is_active) {
2043  command_print(CMD, "semihosting not yet enabled for current target");
2044  return ERROR_FAIL;
2045  }
2046 
2047  if (CMD_ARGC > 0)
2049 
2050  command_print(CMD, "semihosting resumable exit is %s",
2052  ? "enabled" : "disabled");
2053 
2054  return ERROR_OK;
2055 }
2056 
2057 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
2058 {
2061 
2062  if (CMD_ARGC)
2064 
2065  if (!semihosting->is_active) {
2066  LOG_ERROR("semihosting not yet enabled for current target");
2067  return ERROR_FAIL;
2068  }
2069 
2071  LOG_ERROR("This command is usable only from a registered user "
2072  "semihosting event callback.");
2073  return ERROR_FAIL;
2074  }
2075 
2077 
2078  return ERROR_OK;
2079 }
2080 
2081 COMMAND_HANDLER(handle_common_semihosting_basedir_command)
2082 {
2084 
2085  if (CMD_ARGC > 1)
2087 
2088  if (!target) {
2089  LOG_ERROR("No target selected");
2090  return ERROR_FAIL;
2091  }
2092 
2094  if (!semihosting) {
2095  command_print(CMD, "semihosting not supported for current target");
2096  return ERROR_FAIL;
2097  }
2098 
2099  if (!semihosting->is_active) {
2100  command_print(CMD, "semihosting not yet enabled for current target");
2101  return ERROR_FAIL;
2102  }
2103 
2104  if (CMD_ARGC > 0) {
2105  free(semihosting->basedir);
2106  semihosting->basedir = strdup(CMD_ARGV[0]);
2107  if (!semihosting->basedir) {
2108  command_print(CMD, "semihosting failed to allocate memory for basedir!");
2109  return ERROR_FAIL;
2110  }
2111  }
2112 
2113  command_print(CMD, "semihosting base dir: %s",
2115 
2116  return ERROR_OK;
2117 }
2118 
2120  {
2121  .name = "semihosting",
2122  .handler = handle_common_semihosting_command,
2123  .mode = COMMAND_EXEC,
2124  .usage = "['enable'|'disable']",
2125  .help = "activate support for semihosting operations",
2126  },
2127  {
2128  .name = "semihosting_redirect",
2129  .handler = handle_common_semihosting_redirect_command,
2130  .mode = COMMAND_EXEC,
2131  .usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2132  .help = "redirect semihosting IO",
2133  },
2134  {
2135  .name = "semihosting_cmdline",
2136  .handler = handle_common_semihosting_cmdline,
2137  .mode = COMMAND_EXEC,
2138  .usage = "arguments",
2139  .help = "command line arguments to be passed to program",
2140  },
2141  {
2142  .name = "semihosting_fileio",
2143  .handler = handle_common_semihosting_fileio_command,
2144  .mode = COMMAND_EXEC,
2145  .usage = "['enable'|'disable']",
2146  .help = "activate support for semihosting fileio operations",
2147  },
2148  {
2149  .name = "semihosting_resexit",
2150  .handler = handle_common_semihosting_resumable_exit_command,
2151  .mode = COMMAND_EXEC,
2152  .usage = "['enable'|'disable']",
2153  .help = "activate support for semihosting resumable exit",
2154  },
2155  {
2156  .name = "semihosting_read_user_param",
2157  .handler = handle_common_semihosting_read_user_param_command,
2158  .mode = COMMAND_EXEC,
2159  .usage = "",
2160  .help = "read parameters in semihosting-user-cmd-0x10X callbacks",
2161  },
2162  {
2163  .name = "semihosting_basedir",
2164  .handler = handle_common_semihosting_basedir_command,
2165  .mode = COMMAND_EXEC,
2166  .usage = "[dir]",
2167  .help = "set the base directory for semihosting I/O operations",
2168  },
2170 };
static int post_result(struct target *target)
enum arm_mode mode
Definition: armv4_5.c:277
Support functions to access arbitrary bits in a byte array.
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:420
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#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:402
#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:533
#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:253
@ COMMAND_EXEC
Definition: command.h:40
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:4163
void log_socket_error(const char *socket_desc)
Definition: log.c:484
char * alloc_printf(const char *format,...)
Definition: log.c:364
#define ERROR_NOT_IMPLEMENTED
Definition: log.h:174
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
#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
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
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.
@ TARGET_O_WRONLY
@ TARGET_O_TRUNC
@ TARGET_O_RDWR
@ TARGET_O_RDONLY
@ TARGET_O_CREAT
@ TARGET_O_APPEND
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)
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:732
int connection_read(struct connection *connection, void *data, int len)
Definition: server.c:744
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:235
struct service * service
Definition: server.h:41
bool input_pending
Definition: server.h:42
uint64_t param_1
Definition: target.h:219
uint64_t param_4
Definition: target.h:222
uint64_t param_3
Definition: target.h:221
char * identifier
Definition: target.h:218
uint64_t param_2
Definition: target.h:220
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:287
int(* get_gdb_fileio_info)(struct target *target, struct gdb_fileio_info *fileio_info)
Definition: target_type.h:283
Definition: target.h:116
struct semihosting * semihosting
Definition: target.h:209
struct gdb_fileio_info * fileio_info
Definition: target.h:202
struct target_type * type
Definition: target.h:117
uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
Definition: target.c:307
int target_call_event_callbacks(struct target *target, enum target_event event)
Definition: target.c:1764
void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
Definition: target.c:352
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2342
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
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:1265
void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value)
Definition: target.c:343
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:1237
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
void target_handle_event(struct target *target, enum target_event e)
Definition: target.c:4667
uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
Definition: target.c:316
static bool target_was_examined(const struct target *target)
Definition: target.h:436
@ TARGET_EVENT_HALTED
Definition: target.h:252
static const char * target_name(const struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:233
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t count[4]
Definition: vdebug.c:22