1 /***************************************************************************
2 * Copyright (C) 2018 by Liviu Ionescu *
5 * Copyright (C) 2018 by Marvell Technology Group Ltd. *
6 * Written by Nicolas Pitre <nico@marvell.com> *
8 * Copyright (C) 2010 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
11 * Copyright (C) 2016 by Square, Inc. *
12 * Steven Stallion <stallion@squareup.com> *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
26 ***************************************************************************/
30 * Common ARM semihosting support.
32 * Semihosting enables code running on a target to use some of the I/O
33 * facilities on the host computer. The target application must be linked
34 * against a library that forwards operation requests by using an
35 * instruction trapped by the debugger.
37 * Details can be found in
38 * "Semihosting for AArch32 and AArch64, Release 2.0"
39 * https://static.docs.arm.com/100863/0200/semihosting.pdf
48 #include "target_type.h"
49 #include "semihosting_common.h"
51 #include <helper/binarybuffer.h>
52 #include <helper/log.h>
56 * It is not possible to use O_... flags defined in sys/stat.h because they
57 * are not guaranteed to match the values defined by the GDB Remote Protocol.
58 * See https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
61 TARGET_O_RDONLY
= 0x000,
62 TARGET_O_WRONLY
= 0x001,
63 TARGET_O_RDWR
= 0x002,
64 TARGET_O_APPEND
= 0x008,
65 TARGET_O_CREAT
= 0x200,
66 TARGET_O_TRUNC
= 0x400,
67 /* O_EXCL=0x800 is not required in this implementation. */
70 /* GDB remote protocol does not differentiate between text and binary open modes. */
71 static const int open_modeflags
[12] = {
76 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
77 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
78 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
79 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_TRUNC
,
80 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_APPEND
,
81 TARGET_O_WRONLY
| TARGET_O_CREAT
| TARGET_O_APPEND
,
82 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_APPEND
,
83 TARGET_O_RDWR
| TARGET_O_CREAT
| TARGET_O_APPEND
86 static int semihosting_common_fileio_info(struct target
*target
,
87 struct gdb_fileio_info
*fileio_info
);
88 static int semihosting_common_fileio_end(struct target
*target
, int result
,
89 int fileio_errno
, bool ctrl_c
);
91 static int semihosting_read_fields(struct target
*target
, size_t number
,
93 static int semihosting_write_fields(struct target
*target
, size_t number
,
95 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
97 static void semihosting_set_field(struct target
*target
, uint64_t value
,
101 /* Attempts to include gdb_server.h failed. */
102 extern int gdb_actual_connections
;
105 * Initialize common semihosting support.
107 * @param target Pointer to the target to initialize.
110 * @return An error status if there is a problem during initialization.
112 int semihosting_common_init(struct target
*target
, void *setup
,
117 target
->fileio_info
= malloc(sizeof(*target
->fileio_info
));
118 if (!target
->fileio_info
) {
119 LOG_ERROR("out of memory");
122 memset(target
->fileio_info
, 0, sizeof(*target
->fileio_info
));
124 struct semihosting
*semihosting
;
125 semihosting
= malloc(sizeof(*target
->semihosting
));
127 LOG_ERROR("out of memory");
131 semihosting
->is_active
= false;
132 semihosting
->redirect_cfg
= SEMIHOSTING_REDIRECT_CFG_NONE
;
133 semihosting
->tcp_connection
= NULL
;
134 semihosting
->stdin_fd
= -1;
135 semihosting
->stdout_fd
= -1;
136 semihosting
->stderr_fd
= -1;
137 semihosting
->is_fileio
= false;
138 semihosting
->hit_fileio
= false;
139 semihosting
->is_resumable
= false;
140 semihosting
->has_resumable_exit
= false;
141 semihosting
->word_size_bytes
= 0;
142 semihosting
->op
= -1;
143 semihosting
->param
= 0;
144 semihosting
->result
= -1;
145 semihosting
->sys_errno
= -1;
146 semihosting
->cmdline
= NULL
;
148 /* If possible, update it in setup(). */
149 semihosting
->setup_time
= clock();
151 semihosting
->setup
= setup
;
152 semihosting
->post_result
= post_result
;
154 target
->semihosting
= semihosting
;
156 target
->type
->get_gdb_fileio_info
= semihosting_common_fileio_info
;
157 target
->type
->gdb_fileio_end
= semihosting_common_fileio_end
;
162 struct semihosting_tcp_service
{
163 struct semihosting
*semihosting
;
168 static bool semihosting_is_redirected(struct semihosting
*semihosting
, int fd
)
170 if (semihosting
->redirect_cfg
== SEMIHOSTING_REDIRECT_CFG_NONE
)
173 bool is_read_op
= false;
175 switch (semihosting
->op
) {
176 /* check debug semihosting operations: READC, WRITEC and WRITE0 */
177 case SEMIHOSTING_SYS_READC
:
180 case SEMIHOSTING_SYS_WRITEC
:
181 case SEMIHOSTING_SYS_WRITE0
:
182 /* debug operations are redirected when CFG is either DEBUG or ALL */
183 if (semihosting
->redirect_cfg
== SEMIHOSTING_REDIRECT_CFG_STDIO
)
187 /* check stdio semihosting operations: READ and WRITE */
188 case SEMIHOSTING_SYS_READ
:
191 case SEMIHOSTING_SYS_WRITE
:
192 /* stdio operations are redirected when CFG is either STDIO or ALL */
193 if (semihosting
->redirect_cfg
== SEMIHOSTING_REDIRECT_CFG_DEBUG
)
202 return fd
== semihosting
->stdin_fd
;
204 /* write operation */
205 return fd
== semihosting
->stdout_fd
|| fd
== semihosting
->stderr_fd
;
208 static ssize_t
semihosting_redirect_write(struct semihosting
*semihosting
, void *buf
, int size
)
210 if (!semihosting
->tcp_connection
) {
211 LOG_ERROR("No connected TCP client for semihosting");
212 semihosting
->sys_errno
= EBADF
; /* Bad file number */
216 struct semihosting_tcp_service
*service
= semihosting
->tcp_connection
->service
->priv
;
218 int retval
= connection_write(semihosting
->tcp_connection
, buf
, size
);
221 log_socket_error(service
->name
);
226 static ssize_t
semihosting_write(struct semihosting
*semihosting
, int fd
, void *buf
, int size
)
228 if (semihosting_is_redirected(semihosting
, fd
))
229 return semihosting_redirect_write(semihosting
, buf
, size
);
232 return write(fd
, buf
, size
);
235 static ssize_t
semihosting_redirect_read(struct semihosting
*semihosting
, void *buf
, int size
)
237 if (!semihosting
->tcp_connection
) {
238 LOG_ERROR("No connected TCP client for semihosting");
239 semihosting
->sys_errno
= EBADF
; /* Bad file number */
243 struct semihosting_tcp_service
*service
= semihosting
->tcp_connection
->service
->priv
;
245 service
->error
= ERROR_OK
;
246 semihosting
->tcp_connection
->input_pending
= true;
248 int retval
= connection_read(semihosting
->tcp_connection
, buf
, size
);
251 service
->error
= ERROR_SERVER_REMOTE_CLOSED
;
254 log_socket_error(service
->name
);
256 semihosting
->tcp_connection
->input_pending
= false;
261 static inline int semihosting_putchar(struct semihosting
*semihosting
, int fd
, int c
)
263 if (semihosting_is_redirected(semihosting
, fd
))
264 return semihosting_redirect_write(semihosting
, &c
, 1);
266 /* default putchar */
270 static inline ssize_t
semihosting_read(struct semihosting
*semihosting
, int fd
, void *buf
, int size
)
272 if (semihosting_is_redirected(semihosting
, fd
))
273 return semihosting_redirect_read(semihosting
, buf
, size
);
276 ssize_t result
= read(fd
, buf
, size
);
277 semihosting
->sys_errno
= errno
;
282 static inline int semihosting_getchar(struct semihosting
*semihosting
, int fd
)
284 if (semihosting_is_redirected(semihosting
, fd
)) {
287 if (semihosting_redirect_read(semihosting
, &c
, 1) > 0)
293 /* default getchar */
298 * User operation parameter string storage buffer. Contains valid data when the
299 * TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running.
301 static char *semihosting_user_op_params
;
304 * Portable implementation of ARM semihosting calls.
305 * Performs the currently pending semihosting operation
306 * encoded in target->semihosting.
308 int semihosting_common(struct target
*target
)
310 struct semihosting
*semihosting
= target
->semihosting
;
312 /* Silently ignore if the semihosting field was not set. */
316 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
319 * By default return an error.
320 * The actual result must be set by each function
322 semihosting
->result
= -1;
324 /* Most operations are resumable, except the two exit calls. */
325 semihosting
->is_resumable
= true;
329 /* Enough space to hold 4 long words. */
332 LOG_DEBUG("op=0x%x, param=0x%" PRIx64
, semihosting
->op
,
335 switch (semihosting
->op
) {
337 case SEMIHOSTING_SYS_CLOCK
: /* 0x10 */
339 * Returns the number of centiseconds (hundredths of a second)
340 * since the execution started.
342 * Values returned can be of limited use for some benchmarking
343 * purposes because of communication overhead or other
344 * agent-specific factors. For example, with a debug hardware
345 * unit the request is passed back to the host for execution.
346 * This can lead to unpredictable delays in transmission and
347 * process scheduling.
349 * Use this function to calculate time intervals, by calculating
350 * differences between intervals with and without the code
351 * sequence to be timed.
354 * The PARAMETER REGISTER must contain 0. There are no other
358 * On exit, the RETURN REGISTER contains:
359 * - The number of centiseconds since some arbitrary start
360 * point, if the call is successful.
361 * - –1 if the call is not successful. For example, because
362 * of a communications error.
365 clock_t delta
= clock() - semihosting
->setup_time
;
367 semihosting
->result
= delta
/ (CLOCKS_PER_SEC
/ 100);
371 case SEMIHOSTING_SYS_CLOSE
: /* 0x02 */
373 * Closes a file on the host system. The handle must reference
374 * a file that was opened with SYS_OPEN.
377 * On entry, the PARAMETER REGISTER contains a pointer to a
378 * one-field argument block:
379 * - field 1 Contains a handle for an open file.
382 * On exit, the RETURN REGISTER contains:
383 * - 0 if the call is successful
384 * - –1 if the call is not successful.
386 retval
= semihosting_read_fields(target
, 1, fields
);
387 if (retval
!= ERROR_OK
)
390 int fd
= semihosting_get_field(target
, 0, fields
);
391 /* Do not allow to close OpenOCD's own standard streams */
392 if (fd
== 0 || fd
== 1 || fd
== 2) {
393 LOG_DEBUG("ignoring semihosting attempt to close %s",
394 (fd
== 0) ? "stdin" :
395 (fd
== 1) ? "stdout" : "stderr");
396 /* Just pretend success */
397 if (semihosting
->is_fileio
) {
398 semihosting
->result
= 0;
400 semihosting
->result
= 0;
401 semihosting
->sys_errno
= 0;
405 /* Close the descriptor */
406 if (semihosting
->is_fileio
) {
407 semihosting
->hit_fileio
= true;
408 fileio_info
->identifier
= "close";
409 fileio_info
->param_1
= fd
;
411 semihosting
->result
= close(fd
);
412 semihosting
->sys_errno
= errno
;
413 LOG_DEBUG("close(%d)=%d", fd
, (int)semihosting
->result
);
418 case SEMIHOSTING_SYS_ERRNO
: /* 0x13 */
420 * Returns the value of the C library errno variable that is
421 * associated with the semihosting implementation. The errno
422 * variable can be set by a number of C library semihosted
423 * functions, including:
431 * Whether errno is set or not, and to what value, is entirely
432 * host-specific, except where the ISO C standard defines the
436 * There are no parameters. The PARAMETER REGISTER must be 0.
439 * On exit, the RETURN REGISTER contains the value of the C
440 * library errno variable.
442 semihosting
->result
= semihosting
->sys_errno
;
445 case SEMIHOSTING_SYS_EXIT
: /* 0x18 */
447 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
448 * previous versions of the documentation.
450 * An application calls this operation to report an exception
451 * to the debugger directly. The most common use is to report
452 * that execution has completed, using ADP_Stopped_ApplicationExit.
454 * Note: This semihosting operation provides no means for 32-bit
455 * callers to indicate an application exit with a specified exit
456 * code. Semihosting callers may prefer to check for the presence
457 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
458 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
462 * On entry, the PARAMETER register is set to a reason code
463 * describing the cause of the trap. Not all semihosting client
464 * implementations will necessarily trap every corresponding
465 * event. Important reason codes are:
467 * - ADP_Stopped_ApplicationExit 0x20026
468 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
471 * On entry, the PARAMETER REGISTER contains a pointer to a
472 * two-field argument block:
473 * - field 1 The exception type, which is one of the set of
474 * reason codes in the above tables.
475 * - field 2 A subcode, whose meaning depends on the reason
477 * In particular, if field 1 is ADP_Stopped_ApplicationExit
478 * then field 2 is an exit status code, as passed to the C
479 * standard library exit() function. A simulator receiving
480 * this request must notify a connected debugger, if present,
481 * and then exit with the specified status.
484 * No return is expected from these calls. However, it is
485 * possible for the debugger to request that the application
486 * continues by performing an RDI_Execute request or equivalent.
487 * In this case, execution continues with the registers as they
488 * were on entry to the operation, or as subsequently modified
491 if (semihosting
->word_size_bytes
== 8) {
492 retval
= semihosting_read_fields(target
, 2, fields
);
493 if (retval
!= ERROR_OK
)
496 int type
= semihosting_get_field(target
, 0, fields
);
497 int code
= semihosting_get_field(target
, 1, fields
);
499 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
500 if (!gdb_actual_connections
)
504 "semihosting: *** application exited with %d ***\n",
509 "semihosting: application exception %#x\n",
514 if (semihosting
->param
== ADP_STOPPED_APPLICATION_EXIT
) {
515 if (!gdb_actual_connections
)
519 "semihosting: *** application exited normally ***\n");
521 } else if (semihosting
->param
== ADP_STOPPED_RUN_TIME_ERROR
) {
522 /* Chosen more or less arbitrarily to have a nicer message,
523 * otherwise all other return the same exit code 1. */
524 if (!gdb_actual_connections
)
528 "semihosting: *** application exited with error ***\n");
531 if (!gdb_actual_connections
)
535 "semihosting: application exception %#x\n",
536 (unsigned) semihosting
->param
);
540 if (!semihosting
->has_resumable_exit
) {
541 semihosting
->is_resumable
= false;
542 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
546 case SEMIHOSTING_SYS_EXIT_EXTENDED
: /* 0x20 */
548 * This operation is only supported if the semihosting extension
549 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
550 * reported using feature byte 0, bit 0. If this extension is
551 * supported, then the implementation provides a means to
552 * report a normal exit with a nonzero exit status in both 32-bit
553 * and 64-bit semihosting APIs.
555 * The implementation must provide the semihosting call
556 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
558 * SYS_EXIT_EXTENDED is used by an application to report an
559 * exception or exit to the debugger directly. The most common
560 * use is to report that execution has completed, using
561 * ADP_Stopped_ApplicationExit.
564 * On entry, the PARAMETER REGISTER contains a pointer to a
565 * two-field argument block:
566 * - field 1 The exception type, which should be one of the set
567 * of reason codes that are documented for the SYS_EXIT
568 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
569 * - field 2 A subcode, whose meaning depends on the reason
570 * code in field 1. In particular, if field 1 is
571 * ADP_Stopped_ApplicationExit then field 2 is an exit status
572 * code, as passed to the C standard library exit() function.
573 * A simulator receiving this request must notify a connected
574 * debugger, if present, and then exit with the specified status.
577 * No return is expected from these calls.
579 * For the A64 API, this call is identical to the behavior of
580 * the mandatory SYS_EXIT (0x18) call. If this extension is
581 * supported, then both calls must be implemented.
583 retval
= semihosting_read_fields(target
, 2, fields
);
584 if (retval
!= ERROR_OK
)
587 int type
= semihosting_get_field(target
, 0, fields
);
588 int code
= semihosting_get_field(target
, 1, fields
);
590 if (type
== ADP_STOPPED_APPLICATION_EXIT
) {
591 if (!gdb_actual_connections
)
595 "semihosting: *** application exited with %d ***\n",
599 fprintf(stderr
, "semihosting: exception %#x\n",
603 if (!semihosting
->has_resumable_exit
) {
604 semihosting
->is_resumable
= false;
605 return target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
609 case SEMIHOSTING_SYS_FLEN
: /* 0x0C */
611 * Returns the length of a specified file.
614 * On entry, the PARAMETER REGISTER contains a pointer to a
615 * one-field argument block:
616 * - field 1 A handle for a previously opened, seekable file
620 * On exit, the RETURN REGISTER contains:
621 * - The current length of the file object, if the call is
623 * - –1 if an error occurs.
625 if (semihosting
->is_fileio
) {
626 semihosting
->result
= -1;
627 semihosting
->sys_errno
= EINVAL
;
629 retval
= semihosting_read_fields(target
, 1, fields
);
630 if (retval
!= ERROR_OK
)
633 int fd
= semihosting_get_field(target
, 0, fields
);
635 semihosting
->result
= fstat(fd
, &buf
);
636 if (semihosting
->result
== -1) {
637 semihosting
->sys_errno
= errno
;
638 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
641 LOG_DEBUG("fstat(%d)=%d", fd
, (int)semihosting
->result
);
642 semihosting
->result
= buf
.st_size
;
646 case SEMIHOSTING_SYS_GET_CMDLINE
: /* 0x15 */
648 * Returns the command line that is used for the call to the
649 * executable, that is, argc and argv.
652 * On entry, the PARAMETER REGISTER points to a two-field data
653 * block to be used for returning the command string and its length:
654 * - field 1 A pointer to a buffer of at least the size that is
655 * specified in field 2.
656 * - field 2 The length of the buffer in bytes.
660 * If the call is successful, then the RETURN REGISTER contains 0,
661 * the PARAMETER REGISTER is unchanged, and the data block is
662 * updated as follows:
663 * - field 1 A pointer to a null-terminated string of the command
665 * - field 2 The length of the string in bytes.
666 * If the call is not successful, then the RETURN REGISTER
669 * Note: The semihosting implementation might impose limits on
670 * the maximum length of the string that can be transferred.
671 * However, the implementation must be able to support a
672 * command-line length of at least 80 bytes.
674 retval
= semihosting_read_fields(target
, 2, fields
);
675 if (retval
!= ERROR_OK
)
678 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
679 size_t size
= semihosting_get_field(target
, 1, fields
);
681 char *arg
= semihosting
->cmdline
?
682 semihosting
->cmdline
: "";
683 uint32_t len
= strlen(arg
) + 1;
685 semihosting
->result
= -1;
687 semihosting_set_field(target
, len
, 1, fields
);
688 retval
= target_write_buffer(target
, addr
, len
,
690 if (retval
!= ERROR_OK
)
692 semihosting
->result
= 0;
694 retval
= semihosting_write_fields(target
, 2, fields
);
695 if (retval
!= ERROR_OK
)
698 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg
,
699 (int)semihosting
->result
);
703 case SEMIHOSTING_SYS_HEAPINFO
: /* 0x16 */
705 * Returns the system stack and heap parameters.
708 * On entry, the PARAMETER REGISTER contains the address of a
709 * pointer to a four-field data block. The contents of the data
710 * block are filled by the function. The following C-like
711 * pseudocode describes the layout of the block:
720 * On exit, the PARAMETER REGISTER is unchanged and the data
721 * block has been updated.
723 retval
= semihosting_read_fields(target
, 1, fields
);
724 if (retval
!= ERROR_OK
)
727 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
728 /* tell the remote we have no idea */
729 memset(fields
, 0, 4 * semihosting
->word_size_bytes
);
730 retval
= target_write_memory(target
, addr
, 4,
731 semihosting
->word_size_bytes
,
733 if (retval
!= ERROR_OK
)
735 semihosting
->result
= 0;
739 case SEMIHOSTING_SYS_ISERROR
: /* 0x08 */
741 * Determines whether the return code from another semihosting
742 * call is an error status or not.
744 * This call is passed a parameter block containing the error
748 * On entry, the PARAMETER REGISTER contains a pointer to a
749 * one-field data block:
750 * - field 1 The required status word to check.
753 * On exit, the RETURN REGISTER contains:
754 * - 0 if the status field is not an error indication
755 * - A nonzero value if the status field is an error indication.
757 retval
= semihosting_read_fields(target
, 1, fields
);
758 if (retval
!= ERROR_OK
)
761 uint64_t code
= semihosting_get_field(target
, 0, fields
);
762 semihosting
->result
= (code
!= 0);
765 case SEMIHOSTING_SYS_ISTTY
: /* 0x09 */
767 * Checks whether a file is connected to an interactive device.
770 * On entry, the PARAMETER REGISTER contains a pointer to a
771 * one-field argument block:
772 * field 1 A handle for a previously opened file object.
775 * On exit, the RETURN REGISTER contains:
776 * - 1 if the handle identifies an interactive device.
777 * - 0 if the handle identifies a file.
778 * - A value other than 1 or 0 if an error occurs.
780 if (semihosting
->is_fileio
) {
781 semihosting
->hit_fileio
= true;
782 fileio_info
->identifier
= "isatty";
783 fileio_info
->param_1
= semihosting
->param
;
785 retval
= semihosting_read_fields(target
, 1, fields
);
786 if (retval
!= ERROR_OK
)
788 int fd
= semihosting_get_field(target
, 0, fields
);
789 semihosting
->result
= isatty(fd
);
790 semihosting
->sys_errno
= errno
;
791 LOG_DEBUG("isatty(%d)=%d", fd
, (int)semihosting
->result
);
795 case SEMIHOSTING_SYS_OPEN
: /* 0x01 */
797 * Opens a file on the host system.
799 * The file path is specified either as relative to the current
800 * directory of the host process, or absolute, using the path
801 * conventions of the host operating system.
803 * Semihosting implementations must support opening the special
804 * path name :semihosting-features as part of the semihosting
805 * extensions reporting mechanism.
807 * ARM targets interpret the special path name :tt as meaning
808 * the console input stream, for an open-read or the console
809 * output stream, for an open-write. Opening these streams is
810 * performed as part of the standard startup code for those
811 * applications that reference the C stdio streams. The
812 * semihosting extension SH_EXT_STDOUT_STDERR allows the
813 * semihosting caller to open separate output streams
814 * corresponding to stdout and stderr. This extension is
815 * reported using feature byte 0, bit 1. Use SYS_OPEN with
816 * the special path name :semihosting-features to access the
819 * If this extension is supported, the implementation must
820 * support the following additional semantics to SYS_OPEN:
821 * - If the special path name :tt is opened with an fopen
822 * mode requesting write access (w, wb, w+, or w+b), then
823 * this is a request to open stdout.
824 * - If the special path name :tt is opened with a mode
825 * requesting append access (a, ab, a+, or a+b), then this is
826 * a request to open stderr.
829 * On entry, the PARAMETER REGISTER contains a pointer to a
830 * three-field argument block:
831 * - field 1 A pointer to a null-terminated string containing
832 * a file or device name.
833 * - field 2 An integer that specifies the file opening mode.
834 * - field 3 An integer that gives the length of the string
835 * pointed to by field 1.
837 * The length does not include the terminating null character
838 * that must be present.
841 * On exit, the RETURN REGISTER contains:
842 * - A nonzero handle if the call is successful.
843 * - –1 if the call is not successful.
845 retval
= semihosting_read_fields(target
, 3, fields
);
846 if (retval
!= ERROR_OK
)
849 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
850 uint32_t mode
= semihosting_get_field(target
, 1, fields
);
851 size_t len
= semihosting_get_field(target
, 2, fields
);
854 semihosting
->result
= -1;
855 semihosting
->sys_errno
= EINVAL
;
858 uint8_t *fn
= malloc(len
+1);
860 semihosting
->result
= -1;
861 semihosting
->sys_errno
= ENOMEM
;
863 retval
= target_read_memory(target
, addr
, 1, len
, fn
);
864 if (retval
!= ERROR_OK
) {
869 /* TODO: implement the :semihosting-features special file.
871 if (semihosting
->is_fileio
) {
872 if (strcmp((char *)fn
, ":semihosting-features") == 0) {
873 semihosting
->result
= -1;
874 semihosting
->sys_errno
= EINVAL
;
875 } else if (strcmp((char *)fn
, ":tt") == 0) {
877 semihosting
->result
= 0;
879 semihosting
->result
= 1;
881 semihosting
->result
= 2;
883 semihosting
->result
= -1;
885 semihosting
->hit_fileio
= true;
886 fileio_info
->identifier
= "open";
887 fileio_info
->param_1
= addr
;
888 fileio_info
->param_2
= len
;
889 fileio_info
->param_3
= open_modeflags
[mode
];
890 fileio_info
->param_4
= 0644;
893 if (strcmp((char *)fn
, ":tt") == 0) {
895 * - 0-3 ("r") for stdin,
896 * - 4-7 ("w") for stdout,
897 * - 8-11 ("a") for stderr */
899 int fd
= dup(STDIN_FILENO
);
900 semihosting
->result
= fd
;
901 semihosting
->stdin_fd
= fd
;
902 semihosting
->sys_errno
= errno
;
903 LOG_DEBUG("dup(STDIN)=%d",
904 (int)semihosting
->result
);
905 } else if (mode
< 8) {
906 int fd
= dup(STDOUT_FILENO
);
907 semihosting
->result
= fd
;
908 semihosting
->stdout_fd
= fd
;
909 semihosting
->sys_errno
= errno
;
910 LOG_DEBUG("dup(STDOUT)=%d",
911 (int)semihosting
->result
);
913 int fd
= dup(STDERR_FILENO
);
914 semihosting
->result
= fd
;
915 semihosting
->stderr_fd
= fd
;
916 semihosting
->sys_errno
= errno
;
917 LOG_DEBUG("dup(STDERR)=%d",
918 (int)semihosting
->result
);
921 /* cygwin requires the permission setting
922 * otherwise it will fail to reopen a previously
924 semihosting
->result
= open((char *)fn
,
925 open_modeflags
[mode
],
927 semihosting
->sys_errno
= errno
;
928 LOG_DEBUG("open('%s')=%d", fn
,
929 (int)semihosting
->result
);
937 case SEMIHOSTING_SYS_READ
: /* 0x06 */
939 * Reads the contents of a file into a buffer. The file position
940 * is specified either:
941 * - Explicitly by a SYS_SEEK.
942 * - Implicitly one byte beyond the previous SYS_READ or
945 * The file position is at the start of the file when it is
946 * opened, and is lost when the file is closed. Perform the
947 * file operation as a single action whenever possible. For
948 * example, do not split a read of 16KB into four 4KB chunks
949 * unless there is no alternative.
952 * On entry, the PARAMETER REGISTER contains a pointer to a
953 * three-field data block:
954 * - field 1 Contains a handle for a file previously opened
956 * - field 2 Points to a buffer.
957 * - field 3 Contains the number of bytes to read to the buffer
961 * On exit, the RETURN REGISTER contains the number of bytes not
962 * filled in the buffer (buffer_length - bytes_read) as follows:
963 * - If the RETURN REGISTER is 0, the entire buffer was
964 * successfully filled.
965 * - If the RETURN REGISTER is the same as field 3, no bytes
966 * were read (EOF can be assumed).
967 * - If the RETURN REGISTER contains a value smaller than
968 * field 3, the read succeeded but the buffer was only partly
969 * filled. For interactive devices, this is the most common
972 retval
= semihosting_read_fields(target
, 3, fields
);
973 if (retval
!= ERROR_OK
)
976 int fd
= semihosting_get_field(target
, 0, fields
);
977 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
978 size_t len
= semihosting_get_field(target
, 2, fields
);
979 if (semihosting
->is_fileio
) {
980 semihosting
->hit_fileio
= true;
981 fileio_info
->identifier
= "read";
982 fileio_info
->param_1
= fd
;
983 fileio_info
->param_2
= addr
;
984 fileio_info
->param_3
= len
;
986 uint8_t *buf
= malloc(len
);
988 semihosting
->result
= -1;
989 semihosting
->sys_errno
= ENOMEM
;
991 semihosting
->result
= semihosting_read(semihosting
, fd
, buf
, len
);
992 LOG_DEBUG("read(%d, 0x%" PRIx64
", %zu)=%d",
996 (int)semihosting
->result
);
997 if (semihosting
->result
>= 0) {
998 retval
= target_write_buffer(target
, addr
,
1001 if (retval
!= ERROR_OK
) {
1005 /* the number of bytes NOT filled in */
1006 semihosting
->result
= len
-
1007 semihosting
->result
;
1015 case SEMIHOSTING_SYS_READC
: /* 0x07 */
1017 * Reads a byte from the console.
1020 * The PARAMETER REGISTER must contain 0. There are no other
1021 * parameters or values possible.
1024 * On exit, the RETURN REGISTER contains the byte read from
1027 if (semihosting
->is_fileio
) {
1028 LOG_ERROR("SYS_READC not supported by semihosting fileio");
1031 semihosting
->result
= semihosting_getchar(semihosting
, semihosting
->stdin_fd
);
1032 LOG_DEBUG("getchar()=%d", (int)semihosting
->result
);
1035 case SEMIHOSTING_SYS_REMOVE
: /* 0x0E */
1037 * Deletes a specified file on the host filing system.
1040 * On entry, the PARAMETER REGISTER contains a pointer to a
1041 * two-field argument block:
1042 * - field 1 Points to a null-terminated string that gives the
1043 * path name of the file to be deleted.
1044 * - field 2 The length of the string.
1047 * On exit, the RETURN REGISTER contains:
1048 * - 0 if the delete is successful
1049 * - A nonzero, host-specific error code if the delete fails.
1051 retval
= semihosting_read_fields(target
, 2, fields
);
1052 if (retval
!= ERROR_OK
)
1055 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1056 size_t len
= semihosting_get_field(target
, 1, fields
);
1057 if (semihosting
->is_fileio
) {
1058 semihosting
->hit_fileio
= true;
1059 fileio_info
->identifier
= "unlink";
1060 fileio_info
->param_1
= addr
;
1061 fileio_info
->param_2
= len
;
1063 uint8_t *fn
= malloc(len
+1);
1065 semihosting
->result
= -1;
1066 semihosting
->sys_errno
= ENOMEM
;
1069 target_read_memory(target
, addr
, 1, len
,
1071 if (retval
!= ERROR_OK
) {
1076 semihosting
->result
= remove((char *)fn
);
1077 semihosting
->sys_errno
= errno
;
1078 LOG_DEBUG("remove('%s')=%d", fn
,
1079 (int)semihosting
->result
);
1087 case SEMIHOSTING_SYS_RENAME
: /* 0x0F */
1089 * Renames a specified file.
1092 * On entry, the PARAMETER REGISTER contains a pointer to a
1093 * four-field data block:
1094 * - field 1 A pointer to the name of the old file.
1095 * - field 2 The length of the old filename.
1096 * - field 3 A pointer to the new filename.
1097 * - field 4 The length of the new filename. Both strings are
1101 * On exit, the RETURN REGISTER contains:
1102 * - 0 if the rename is successful.
1103 * - A nonzero, host-specific error code if the rename fails.
1105 retval
= semihosting_read_fields(target
, 4, fields
);
1106 if (retval
!= ERROR_OK
)
1109 uint64_t addr1
= semihosting_get_field(target
, 0, fields
);
1110 size_t len1
= semihosting_get_field(target
, 1, fields
);
1111 uint64_t addr2
= semihosting_get_field(target
, 2, fields
);
1112 size_t len2
= semihosting_get_field(target
, 3, fields
);
1113 if (semihosting
->is_fileio
) {
1114 semihosting
->hit_fileio
= true;
1115 fileio_info
->identifier
= "rename";
1116 fileio_info
->param_1
= addr1
;
1117 fileio_info
->param_2
= len1
;
1118 fileio_info
->param_3
= addr2
;
1119 fileio_info
->param_4
= len2
;
1121 uint8_t *fn1
= malloc(len1
+1);
1122 uint8_t *fn2
= malloc(len2
+1);
1126 semihosting
->result
= -1;
1127 semihosting
->sys_errno
= ENOMEM
;
1129 retval
= target_read_memory(target
, addr1
, 1, len1
,
1131 if (retval
!= ERROR_OK
) {
1136 retval
= target_read_memory(target
, addr2
, 1, len2
,
1138 if (retval
!= ERROR_OK
) {
1145 semihosting
->result
= rename((char *)fn1
,
1147 semihosting
->sys_errno
= errno
;
1148 LOG_DEBUG("rename('%s', '%s')=%d", fn1
, fn2
,
1149 (int)semihosting
->result
);
1158 case SEMIHOSTING_SYS_SEEK
: /* 0x0A */
1160 * Seeks to a specified position in a file using an offset
1161 * specified from the start of the file. The file is assumed
1162 * to be a byte array and the offset is given in bytes.
1165 * On entry, the PARAMETER REGISTER contains a pointer to a
1166 * two-field data block:
1167 * - field 1 A handle for a seekable file object.
1168 * - field 2 The absolute byte position to seek to.
1171 * On exit, the RETURN REGISTER contains:
1172 * - 0 if the request is successful.
1173 * - A negative value if the request is not successful.
1174 * Use SYS_ERRNO to read the value of the host errno variable
1175 * describing the error.
1177 * Note: The effect of seeking outside the current extent of
1178 * the file object is undefined.
1180 retval
= semihosting_read_fields(target
, 2, fields
);
1181 if (retval
!= ERROR_OK
)
1184 int fd
= semihosting_get_field(target
, 0, fields
);
1185 off_t pos
= semihosting_get_field(target
, 1, fields
);
1186 if (semihosting
->is_fileio
) {
1187 semihosting
->hit_fileio
= true;
1188 fileio_info
->identifier
= "lseek";
1189 fileio_info
->param_1
= fd
;
1190 fileio_info
->param_2
= pos
;
1191 fileio_info
->param_3
= SEEK_SET
;
1193 semihosting
->result
= lseek(fd
, pos
, SEEK_SET
);
1194 semihosting
->sys_errno
= errno
;
1195 LOG_DEBUG("lseek(%d, %d)=%d", fd
, (int)pos
,
1196 (int)semihosting
->result
);
1197 if (semihosting
->result
== pos
)
1198 semihosting
->result
= 0;
1203 case SEMIHOSTING_SYS_SYSTEM
: /* 0x12 */
1205 * Passes a command to the host command-line interpreter.
1206 * This enables you to execute a system command such as dir,
1207 * ls, or pwd. The terminal I/O is on the host, and is not
1208 * visible to the target.
1211 * On entry, the PARAMETER REGISTER contains a pointer to a
1212 * two-field argument block:
1213 * - field 1 Points to a string to be passed to the host
1214 * command-line interpreter.
1215 * - field 2 The length of the string.
1218 * On exit, the RETURN REGISTER contains the return status.
1221 /* Provide SYS_SYSTEM functionality. Uses the
1222 * libc system command, there may be a reason *NOT*
1223 * to use this, but as I can't think of one, I
1224 * implemented it this way.
1226 retval
= semihosting_read_fields(target
, 2, fields
);
1227 if (retval
!= ERROR_OK
)
1230 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1231 size_t len
= semihosting_get_field(target
, 1, fields
);
1232 if (semihosting
->is_fileio
) {
1233 semihosting
->hit_fileio
= true;
1234 fileio_info
->identifier
= "system";
1235 fileio_info
->param_1
= addr
;
1236 fileio_info
->param_2
= len
;
1238 uint8_t *cmd
= malloc(len
+1);
1240 semihosting
->result
= -1;
1241 semihosting
->sys_errno
= ENOMEM
;
1243 retval
= target_read_memory(target
,
1248 if (retval
!= ERROR_OK
) {
1253 semihosting
->result
= system(
1255 LOG_DEBUG("system('%s')=%d",
1257 (int)semihosting
->result
);
1266 case SEMIHOSTING_SYS_TIME
: /* 0x11 */
1268 * Returns the number of seconds since 00:00 January 1, 1970.
1269 * This value is real-world time, regardless of any debug agent
1273 * There are no parameters.
1276 * On exit, the RETURN REGISTER contains the number of seconds.
1278 semihosting
->result
= time(NULL
);
1281 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1283 * Writes the contents of a buffer to a specified file at the
1284 * current file position. The file position is specified either:
1285 * - Explicitly, by a SYS_SEEK.
1286 * - Implicitly as one byte beyond the previous SYS_READ or
1287 * SYS_WRITE request.
1289 * The file position is at the start of the file when the file
1290 * is opened, and is lost when the file is closed.
1292 * Perform the file operation as a single action whenever
1293 * possible. For example, do not split a write of 16KB into
1294 * four 4KB chunks unless there is no alternative.
1297 * On entry, the PARAMETER REGISTER contains a pointer to a
1298 * three-field data block:
1299 * - field 1 Contains a handle for a file previously opened
1301 * - field 2 Points to the memory containing the data to be written.
1302 * - field 3 Contains the number of bytes to be written from
1303 * the buffer to the file.
1306 * On exit, the RETURN REGISTER contains:
1307 * - 0 if the call is successful.
1308 * - The number of bytes that are not written, if there is an error.
1310 retval
= semihosting_read_fields(target
, 3, fields
);
1311 if (retval
!= ERROR_OK
)
1314 int fd
= semihosting_get_field(target
, 0, fields
);
1315 uint64_t addr
= semihosting_get_field(target
, 1, fields
);
1316 size_t len
= semihosting_get_field(target
, 2, fields
);
1317 if (semihosting
->is_fileio
) {
1318 semihosting
->hit_fileio
= true;
1319 fileio_info
->identifier
= "write";
1320 fileio_info
->param_1
= fd
;
1321 fileio_info
->param_2
= addr
;
1322 fileio_info
->param_3
= len
;
1324 uint8_t *buf
= malloc(len
);
1326 semihosting
->result
= -1;
1327 semihosting
->sys_errno
= ENOMEM
;
1329 retval
= target_read_buffer(target
, addr
, len
, buf
);
1330 if (retval
!= ERROR_OK
) {
1334 semihosting
->result
= semihosting_write(semihosting
, fd
, buf
, len
);
1335 semihosting
->sys_errno
= errno
;
1336 LOG_DEBUG("write(%d, 0x%" PRIx64
", %zu)=%d",
1340 (int)semihosting
->result
);
1341 if (semihosting
->result
>= 0) {
1342 /* The number of bytes that are NOT written.
1344 semihosting
->result
= len
-
1345 semihosting
->result
;
1354 case SEMIHOSTING_SYS_WRITEC
: /* 0x03 */
1356 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1357 * to the debug channel. When executed under a semihosting
1358 * debugger, the character appears on the host debugger console.
1361 * On entry, the PARAMETER REGISTER contains a pointer to the
1365 * None. The RETURN REGISTER is corrupted.
1367 if (semihosting
->is_fileio
) {
1368 semihosting
->hit_fileio
= true;
1369 fileio_info
->identifier
= "write";
1370 fileio_info
->param_1
= 1;
1371 fileio_info
->param_2
= semihosting
->param
;
1372 fileio_info
->param_3
= 1;
1374 uint64_t addr
= semihosting
->param
;
1376 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1377 if (retval
!= ERROR_OK
)
1379 semihosting_putchar(semihosting
, semihosting
->stdout_fd
, c
);
1380 semihosting
->result
= 0;
1384 case SEMIHOSTING_SYS_WRITE0
: /* 0x04 */
1386 * Writes a null-terminated string to the debug channel.
1387 * When executed under a semihosting debugger, the characters
1388 * appear on the host debugger console.
1391 * On entry, the PARAMETER REGISTER contains a pointer to the
1392 * first byte of the string.
1395 * None. The RETURN REGISTER is corrupted.
1397 if (semihosting
->is_fileio
) {
1399 uint64_t addr
= semihosting
->param
;
1402 retval
= target_read_memory(target
, addr
, 1, 1, &c
);
1403 if (retval
!= ERROR_OK
)
1409 semihosting
->hit_fileio
= true;
1410 fileio_info
->identifier
= "write";
1411 fileio_info
->param_1
= 1;
1412 fileio_info
->param_2
= semihosting
->param
;
1413 fileio_info
->param_3
= count
;
1415 uint64_t addr
= semihosting
->param
;
1418 retval
= target_read_memory(target
, addr
++, 1, 1, &c
);
1419 if (retval
!= ERROR_OK
)
1423 semihosting_putchar(semihosting
, semihosting
->stdout_fd
, c
);
1425 semihosting
->result
= 0;
1429 case SEMIHOSTING_USER_CMD_0x100
... SEMIHOSTING_USER_CMD_0x107
:
1431 * This is a user defined operation (while user cmds 0x100-0x1ff
1432 * are possible, only 0x100-0x107 are currently implemented).
1434 * Reads the user operation parameters from target, then fires the
1435 * corresponding target event. When the target callbacks returned,
1436 * cleans up the command parameter buffer.
1439 * On entry, the PARAMETER REGISTER contains a pointer to a
1440 * two-field data block:
1441 * - field 1 Contains a pointer to the bound command parameter
1443 * - field 2 Contains the command parameter string length
1446 * On exit, the RETURN REGISTER contains the return status.
1449 assert(!semihosting_user_op_params
);
1451 retval
= semihosting_read_fields(target
, 2, fields
);
1452 if (retval
!= ERROR_OK
) {
1453 LOG_ERROR("Failed to read fields for user defined command"
1454 " op=0x%x", semihosting
->op
);
1458 uint64_t addr
= semihosting_get_field(target
, 0, fields
);
1460 size_t len
= semihosting_get_field(target
, 1, fields
);
1461 if (len
> SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH
) {
1462 LOG_ERROR("The maximum length for user defined command "
1463 "parameter is %u, received length is %zu (op=0x%x)",
1464 SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH
,
1470 semihosting_user_op_params
= malloc(len
+ 1);
1471 if (!semihosting_user_op_params
)
1473 semihosting_user_op_params
[len
] = 0;
1475 retval
= target_read_buffer(target
, addr
, len
,
1476 (uint8_t *)(semihosting_user_op_params
));
1477 if (retval
!= ERROR_OK
) {
1478 LOG_ERROR("Failed to read from target, semihosting op=0x%x",
1480 free(semihosting_user_op_params
);
1481 semihosting_user_op_params
= NULL
;
1485 target_handle_event(target
, semihosting
->op
);
1486 free(semihosting_user_op_params
);
1487 semihosting_user_op_params
= NULL
;
1489 semihosting
->result
= 0;
1494 case SEMIHOSTING_SYS_ELAPSED
: /* 0x30 */
1496 * Returns the number of elapsed target ticks since execution
1498 * Use SYS_TICKFREQ to determine the tick frequency.
1501 * On entry, the PARAMETER REGISTER points to a two-field data
1502 * block to be used for returning the number of elapsed ticks:
1503 * - field 1 The least significant field and is at the low address.
1504 * - field 2 The most significant field and is at the high address.
1507 * On entry the PARAMETER REGISTER points to a one-field data
1508 * block to be used for returning the number of elapsed ticks:
1509 * - field 1 The number of elapsed ticks as a 64-bit value.
1513 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1514 * REGISTER is unchanged, and the data block pointed to by the
1515 * PARAMETER REGISTER is filled in with the number of elapsed
1517 * - On failure, the RETURN REGISTER contains -1, and the
1518 * PARAMETER REGISTER contains -1.
1520 * Note: Some semihosting implementations might not support this
1521 * semihosting operation, and they always return -1 in the
1525 case SEMIHOSTING_SYS_TICKFREQ
: /* 0x31 */
1527 * Returns the tick frequency.
1530 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1533 * On exit, the RETURN REGISTER contains either:
1534 * - The number of ticks per second.
1535 * - –1 if the target does not know the value of one tick.
1537 * Note: Some semihosting implementations might not support
1538 * this semihosting operation, and they always return -1 in the
1542 case SEMIHOSTING_SYS_TMPNAM
: /* 0x0D */
1544 * Returns a temporary name for a file identified by a system
1548 * On entry, the PARAMETER REGISTER contains a pointer to a
1549 * three-word argument block:
1550 * - field 1 A pointer to a buffer.
1551 * - field 2 A target identifier for this filename. Its value
1552 * must be an integer in the range 0-255.
1553 * - field 3 Contains the length of the buffer. The length must
1554 * be at least the value of L_tmpnam on the host system.
1557 * On exit, the RETURN REGISTER contains:
1558 * - 0 if the call is successful.
1559 * - –1 if an error occurs.
1561 * The buffer pointed to by the PARAMETER REGISTER contains
1562 * the filename, prefixed with a suitable directory name.
1563 * If you use the same target identifier again, the same
1564 * filename is returned.
1566 * Note: The returned string must be null-terminated.
1570 fprintf(stderr
, "semihosting: unsupported call %#x\n",
1571 (unsigned) semihosting
->op
);
1572 semihosting
->result
= -1;
1573 semihosting
->sys_errno
= ENOTSUP
;
1576 if (!semihosting
->hit_fileio
) {
1577 retval
= semihosting
->post_result(target
);
1578 if (retval
!= ERROR_OK
) {
1579 LOG_ERROR("Failed to post semihosting result");
1587 /* -------------------------------------------------------------------------
1588 * Local functions. */
1590 static int semihosting_common_fileio_info(struct target
*target
,
1591 struct gdb_fileio_info
*fileio_info
)
1593 struct semihosting
*semihosting
= target
->semihosting
;
1598 * To avoid unnecessary duplication, semihosting prepares the
1599 * fileio_info structure out-of-band when the target halts. See
1600 * do_semihosting for more detail.
1602 if (!semihosting
->is_fileio
|| !semihosting
->hit_fileio
)
1608 static int semihosting_common_fileio_end(struct target
*target
, int result
,
1609 int fileio_errno
, bool ctrl_c
)
1611 struct gdb_fileio_info
*fileio_info
= target
->fileio_info
;
1612 struct semihosting
*semihosting
= target
->semihosting
;
1616 /* clear pending status */
1617 semihosting
->hit_fileio
= false;
1619 semihosting
->result
= result
;
1620 semihosting
->sys_errno
= fileio_errno
;
1623 * Some fileio results do not match up with what the semihosting
1624 * operation expects; for these operations, we munge the results
1627 switch (semihosting
->op
) {
1628 case SEMIHOSTING_SYS_WRITE
: /* 0x05 */
1630 semihosting
->result
= fileio_info
->param_3
;
1632 semihosting
->result
= 0;
1635 case SEMIHOSTING_SYS_READ
: /* 0x06 */
1636 if (result
== (int)fileio_info
->param_3
)
1637 semihosting
->result
= 0;
1639 semihosting
->result
= fileio_info
->param_3
;
1642 case SEMIHOSTING_SYS_SEEK
: /* 0x0a */
1644 semihosting
->result
= 0;
1648 return semihosting
->post_result(target
);
1652 * Read all fields of a command from target to buffer.
1654 static int semihosting_read_fields(struct target
*target
, size_t number
,
1657 struct semihosting
*semihosting
= target
->semihosting
;
1658 /* Use 4-byte multiples to trigger fast memory access. */
1659 return target_read_memory(target
, semihosting
->param
, 4,
1660 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1664 * Write all fields of a command from buffer to target.
1666 static int semihosting_write_fields(struct target
*target
, size_t number
,
1669 struct semihosting
*semihosting
= target
->semihosting
;
1670 /* Use 4-byte multiples to trigger fast memory access. */
1671 return target_write_memory(target
, semihosting
->param
, 4,
1672 number
* (semihosting
->word_size_bytes
/ 4), fields
);
1676 * Extract a field from the buffer, considering register size and endianness.
1678 static uint64_t semihosting_get_field(struct target
*target
, size_t index
,
1681 struct semihosting
*semihosting
= target
->semihosting
;
1682 if (semihosting
->word_size_bytes
== 8)
1683 return target_buffer_get_u64(target
, fields
+ (index
* 8));
1685 return target_buffer_get_u32(target
, fields
+ (index
* 4));
1689 * Store a field in the buffer, considering register size and endianness.
1691 static void semihosting_set_field(struct target
*target
, uint64_t value
,
1695 struct semihosting
*semihosting
= target
->semihosting
;
1696 if (semihosting
->word_size_bytes
== 8)
1697 target_buffer_set_u64(target
, fields
+ (index
* 8), value
);
1699 target_buffer_set_u32(target
, fields
+ (index
* 4), value
);
1702 /* -------------------------------------------------------------------------
1703 * Semihosting redirect over TCP structs and functions */
1705 static int semihosting_service_new_connection_handler(struct connection
*connection
)
1707 struct semihosting_tcp_service
*service
= connection
->service
->priv
;
1708 service
->semihosting
->tcp_connection
= connection
;
1713 static int semihosting_service_input_handler(struct connection
*connection
)
1715 struct semihosting_tcp_service
*service
= connection
->service
->priv
;
1717 if (!connection
->input_pending
) {
1718 /* consume received data, not for semihosting IO */
1719 const int buf_len
= 100;
1721 int bytes_read
= connection_read(connection
, buf
, buf_len
);
1723 if (bytes_read
== 0) {
1724 return ERROR_SERVER_REMOTE_CLOSED
;
1725 } else if (bytes_read
== -1) {
1726 LOG_ERROR("error during read: %s", strerror(errno
));
1727 return ERROR_SERVER_REMOTE_CLOSED
;
1729 } else if (service
->error
!= ERROR_OK
) {
1730 return ERROR_SERVER_REMOTE_CLOSED
;
1736 static int semihosting_service_connection_closed_handler(struct connection
*connection
)
1738 struct semihosting_tcp_service
*service
= connection
->service
->priv
;
1740 free(service
->name
);
1747 static void semihosting_tcp_close_cnx(struct semihosting
*semihosting
)
1749 if (!semihosting
->tcp_connection
)
1752 struct service
*service
= semihosting
->tcp_connection
->service
;
1753 remove_service(service
->name
, service
->port
);
1754 semihosting
->tcp_connection
= NULL
;
1758 static const struct service_driver semihosting_service_driver
= {
1759 .name
= "semihosting",
1760 .new_connection_during_keep_alive_handler
= NULL
,
1761 .new_connection_handler
= semihosting_service_new_connection_handler
,
1762 .input_handler
= semihosting_service_input_handler
,
1763 .connection_closed_handler
= semihosting_service_connection_closed_handler
,
1764 .keep_client_alive_handler
= NULL
,
1767 /* -------------------------------------------------------------------------
1768 * Common semihosting commands handlers. */
1770 COMMAND_HANDLER(handle_common_semihosting_command
)
1772 struct target
*target
= get_current_target(CMD_CTX
);
1775 LOG_ERROR("No target selected");
1779 struct semihosting
*semihosting
= target
->semihosting
;
1781 command_print(CMD
, "semihosting not supported for current target");
1788 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], is_active
);
1790 if (!target_was_examined(target
)) {
1791 LOG_ERROR("Target not examined yet");
1795 if (semihosting
&& semihosting
->setup(target
, is_active
) != ERROR_OK
) {
1796 LOG_ERROR("Failed to Configure semihosting");
1800 /* FIXME never let that "catch" be dropped! (???) */
1801 semihosting
->is_active
= is_active
;
1804 command_print(CMD
, "semihosting is %s",
1805 semihosting
->is_active
1806 ? "enabled" : "disabled");
1811 COMMAND_HANDLER(handle_common_semihosting_redirect_command
)
1813 struct target
*target
= get_current_target(CMD_CTX
);
1815 if (target
== NULL
) {
1816 LOG_ERROR("No target selected");
1820 struct semihosting
*semihosting
= target
->semihosting
;
1822 command_print(CMD
, "semihosting not supported for current target");
1826 if (!semihosting
->is_active
) {
1827 command_print(CMD
, "semihosting not yet enabled for current target");
1831 enum semihosting_redirect_config cfg
;
1835 return ERROR_COMMAND_SYNTAX_ERROR
;
1837 if (strcmp(CMD_ARGV
[0], "disable") == 0) {
1838 cfg
= SEMIHOSTING_REDIRECT_CFG_NONE
;
1840 return ERROR_COMMAND_SYNTAX_ERROR
;
1841 } else if (strcmp(CMD_ARGV
[0], "tcp") == 0) {
1842 if (CMD_ARGC
< 2 || CMD_ARGC
> 3)
1843 return ERROR_COMMAND_SYNTAX_ERROR
;
1847 cfg
= SEMIHOSTING_REDIRECT_CFG_ALL
;
1848 if (CMD_ARGC
== 3) {
1849 if (strcmp(CMD_ARGV
[2], "debug") == 0)
1850 cfg
= SEMIHOSTING_REDIRECT_CFG_DEBUG
;
1851 else if (strcmp(CMD_ARGV
[2], "stdio") == 0)
1852 cfg
= SEMIHOSTING_REDIRECT_CFG_STDIO
;
1853 else if (strcmp(CMD_ARGV
[2], "all") != 0)
1854 return ERROR_COMMAND_SYNTAX_ERROR
;
1857 return ERROR_COMMAND_SYNTAX_ERROR
;
1860 semihosting_tcp_close_cnx(semihosting
);
1861 semihosting
->redirect_cfg
= SEMIHOSTING_REDIRECT_CFG_NONE
;
1863 if (cfg
!= SEMIHOSTING_REDIRECT_CFG_NONE
) {
1864 struct semihosting_tcp_service
*service
=
1865 calloc(1, sizeof(struct semihosting_tcp_service
));
1867 LOG_ERROR("Failed to allocate semihosting TCP service.");
1871 service
->semihosting
= semihosting
;
1873 service
->name
= alloc_printf("%s semihosting service", target_name(target
));
1874 if (!service
->name
) {
1875 LOG_ERROR("Out of memory");
1880 int ret
= add_service(&semihosting_service_driver
,
1883 if (ret
!= ERROR_OK
) {
1884 LOG_ERROR("failed to initialize %s", service
->name
);
1885 free(service
->name
);
1891 semihosting
->redirect_cfg
= cfg
;
1896 COMMAND_HANDLER(handle_common_semihosting_fileio_command
)
1898 struct target
*target
= get_current_target(CMD_CTX
);
1901 LOG_ERROR("No target selected");
1905 struct semihosting
*semihosting
= target
->semihosting
;
1907 command_print(CMD
, "semihosting not supported for current target");
1911 if (!semihosting
->is_active
) {
1912 command_print(CMD
, "semihosting not yet enabled for current target");
1917 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->is_fileio
);
1919 command_print(CMD
, "semihosting fileio is %s",
1920 semihosting
->is_fileio
1921 ? "enabled" : "disabled");
1926 COMMAND_HANDLER(handle_common_semihosting_cmdline
)
1928 struct target
*target
= get_current_target(CMD_CTX
);
1932 LOG_ERROR("No target selected");
1936 struct semihosting
*semihosting
= target
->semihosting
;
1938 command_print(CMD
, "semihosting not supported for current target");
1942 free(semihosting
->cmdline
);
1943 semihosting
->cmdline
= CMD_ARGC
> 0 ? strdup(CMD_ARGV
[0]) : NULL
;
1945 for (i
= 1; i
< CMD_ARGC
; i
++) {
1946 char *cmdline
= alloc_printf("%s %s", semihosting
->cmdline
, CMD_ARGV
[i
]);
1949 free(semihosting
->cmdline
);
1950 semihosting
->cmdline
= cmdline
;
1953 command_print(CMD
, "semihosting command line is [%s]",
1954 semihosting
->cmdline
);
1959 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command
)
1961 struct target
*target
= get_current_target(CMD_CTX
);
1964 LOG_ERROR("No target selected");
1968 struct semihosting
*semihosting
= target
->semihosting
;
1970 command_print(CMD
, "semihosting not supported for current target");
1974 if (!semihosting
->is_active
) {
1975 command_print(CMD
, "semihosting not yet enabled for current target");
1980 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], semihosting
->has_resumable_exit
);
1982 command_print(CMD
, "semihosting resumable exit is %s",
1983 semihosting
->has_resumable_exit
1984 ? "enabled" : "disabled");
1989 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command
)
1991 struct target
*target
= get_current_target(CMD_CTX
);
1992 struct semihosting
*semihosting
= target
->semihosting
;
1995 return ERROR_COMMAND_SYNTAX_ERROR
;
1997 if (!semihosting
->is_active
) {
1998 LOG_ERROR("semihosting not yet enabled for current target");
2002 if (!semihosting_user_op_params
) {
2003 LOG_ERROR("This command is usable only from a registered user "
2004 "semihosting event callback.");
2008 command_print_sameline(CMD
, "%s", semihosting_user_op_params
);
2013 const struct command_registration semihosting_common_handlers
[] = {
2015 .name
= "semihosting",
2016 .handler
= handle_common_semihosting_command
,
2017 .mode
= COMMAND_EXEC
,
2018 .usage
= "['enable'|'disable']",
2019 .help
= "activate support for semihosting operations",
2022 .name
= "semihosting_redirect",
2023 .handler
= handle_common_semihosting_redirect_command
,
2024 .mode
= COMMAND_EXEC
,
2025 .usage
= "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2026 .help
= "redirect semihosting IO",
2029 .name
= "semihosting_cmdline",
2030 .handler
= handle_common_semihosting_cmdline
,
2031 .mode
= COMMAND_EXEC
,
2032 .usage
= "arguments",
2033 .help
= "command line arguments to be passed to program",
2036 .name
= "semihosting_fileio",
2037 .handler
= handle_common_semihosting_fileio_command
,
2038 .mode
= COMMAND_EXEC
,
2039 .usage
= "['enable'|'disable']",
2040 .help
= "activate support for semihosting fileio operations",
2043 .name
= "semihosting_resexit",
2044 .handler
= handle_common_semihosting_resumable_exit_command
,
2045 .mode
= COMMAND_EXEC
,
2046 .usage
= "['enable'|'disable']",
2047 .help
= "activate support for semihosting resumable exit",
2050 .name
= "semihosting_read_user_param",
2051 .handler
= handle_common_semihosting_read_user_param_command
,
2052 .mode
= COMMAND_EXEC
,
2054 .help
= "read parameters in semihosting-user-cmd-0x10X callbacks",
2056 COMMAND_REGISTRATION_DONE