Remove other '_s' suffix from structs
[openocd.git] / src / target / semihosting_common.c
blob1eb195712e95c8b872c1113d38b9d8887ed71314
1 // SPDX-License-Identifier: GPL-2.0-or-later
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 ***************************************************************************/
17 /**
18 * @file
19 * Common ARM semihosting support.
21 * Semihosting enables code running on a target to use some of the I/O
22 * facilities on the host computer. The target application must be linked
23 * against a library that forwards operation requests by using an
24 * instruction trapped by the debugger.
26 * Details can be found in
27 * "Semihosting for AArch32 and AArch64, Release 2.0"
28 * https://static.docs.arm.com/100863/0200/semihosting.pdf
29 * from ARM Ltd.
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include "target.h"
37 #include "target_type.h"
38 #include "semihosting_common.h"
40 #include <helper/binarybuffer.h>
41 #include <helper/log.h>
42 #include <server/gdb_server.h>
43 #include <sys/stat.h>
45 /**
46 * It is not possible to use O_... flags defined in sys/stat.h because they
47 * are not guaranteed to match the values defined by the GDB Remote Protocol.
48 * See https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
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. */
60 /* GDB remote protocol does not differentiate between text and binary open modes. */
61 static const int open_gdb_modeflags[12] = {
62 TARGET_O_RDONLY,
63 TARGET_O_RDONLY,
64 TARGET_O_RDWR,
65 TARGET_O_RDWR,
66 TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,
67 TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,
68 TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_TRUNC,
69 TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_TRUNC,
70 TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,
71 TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,
72 TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND,
73 TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND
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
91 static int semihosting_common_fileio_info(struct target *target,
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);
96 /**
97 * Initialize common semihosting support.
99 * @param target Pointer to the target to initialize.
100 * @param setup
101 * @param post_result
102 * @return An error status if there is a problem during initialization.
104 int semihosting_common_init(struct target *target, void *setup,
105 void *post_result)
107 LOG_DEBUG(" ");
109 target->fileio_info = malloc(sizeof(*target->fileio_info));
110 if (!target->fileio_info) {
111 LOG_ERROR("out of memory");
112 return ERROR_FAIL;
114 memset(target->fileio_info, 0, sizeof(*target->fileio_info));
116 struct semihosting *semihosting;
117 semihosting = malloc(sizeof(*target->semihosting));
118 if (!semihosting) {
119 LOG_ERROR("out of memory");
120 return ERROR_FAIL;
123 semihosting->is_active = false;
124 semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
125 semihosting->tcp_connection = NULL;
126 semihosting->stdin_fd = -1;
127 semihosting->stdout_fd = -1;
128 semihosting->stderr_fd = -1;
129 semihosting->is_fileio = false;
130 semihosting->hit_fileio = false;
131 semihosting->is_resumable = false;
132 semihosting->has_resumable_exit = false;
133 semihosting->word_size_bytes = 0;
134 semihosting->op = -1;
135 semihosting->param = 0;
136 semihosting->result = -1;
137 semihosting->sys_errno = -1;
138 semihosting->cmdline = NULL;
139 semihosting->basedir = NULL;
141 /* If possible, update it in setup(). */
142 semihosting->setup_time = clock();
144 semihosting->setup = setup;
145 semihosting->post_result = post_result;
146 semihosting->user_command_extension = NULL;
148 target->semihosting = semihosting;
150 target->type->get_gdb_fileio_info = semihosting_common_fileio_info;
151 target->type->gdb_fileio_end = semihosting_common_fileio_end;
153 return ERROR_OK;
156 struct semihosting_tcp_service {
157 struct semihosting *semihosting;
158 char *name;
159 int error;
162 static bool semihosting_is_redirected(struct semihosting *semihosting, int fd)
164 if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_NONE)
165 return false;
167 bool is_read_op = false;
169 switch (semihosting->op) {
170 /* check debug semihosting operations: READC, WRITEC and WRITE0 */
171 case SEMIHOSTING_SYS_READC:
172 is_read_op = true;
173 /* fall through */
174 case SEMIHOSTING_SYS_WRITEC:
175 case SEMIHOSTING_SYS_WRITE0:
176 /* debug operations are redirected when CFG is either DEBUG or ALL */
177 if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_STDIO)
178 return false;
179 break;
181 /* check stdio semihosting operations: READ and WRITE */
182 case SEMIHOSTING_SYS_READ:
183 is_read_op = true;
184 /* fall through */
185 case SEMIHOSTING_SYS_WRITE:
186 /* stdio operations are redirected when CFG is either STDIO or ALL */
187 if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_DEBUG)
188 return false;
189 break;
191 default:
192 return false;
195 if (is_read_op)
196 return fd == semihosting->stdin_fd;
198 /* write operation */
199 return fd == semihosting->stdout_fd || fd == semihosting->stderr_fd;
202 static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size)
204 if (!semihosting->tcp_connection) {
205 LOG_ERROR("No connected TCP client for semihosting");
206 semihosting->sys_errno = EBADF; /* Bad file number */
207 return -1;
210 struct semihosting_tcp_service *service = semihosting->tcp_connection->service->priv;
212 int retval = connection_write(semihosting->tcp_connection, buf, size);
214 if (retval < 0)
215 log_socket_error(service->name);
217 return retval;
220 static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size)
222 if (semihosting_is_redirected(semihosting, fd))
223 return semihosting_redirect_write(semihosting, buf, size);
225 /* default write */
226 int result = write(fd, buf, size);
227 if (result == -1)
228 semihosting->sys_errno = errno;
229 return result;
232 static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
234 if (!semihosting->tcp_connection) {
235 LOG_ERROR("No connected TCP client for semihosting");
236 semihosting->sys_errno = EBADF; /* Bad file number */
237 return -1;
240 struct semihosting_tcp_service *service = semihosting->tcp_connection->service->priv;
242 service->error = ERROR_OK;
243 semihosting->tcp_connection->input_pending = true;
245 int retval = connection_read(semihosting->tcp_connection, buf, size);
247 if (retval <= 0)
248 service->error = ERROR_SERVER_REMOTE_CLOSED;
250 if (retval < 0)
251 log_socket_error(service->name);
253 semihosting->tcp_connection->input_pending = false;
255 return retval;
258 static inline int semihosting_putchar(struct semihosting *semihosting, int fd, int c)
260 if (semihosting_is_redirected(semihosting, fd))
261 return semihosting_redirect_write(semihosting, &c, 1);
263 /* default putchar */
264 return putchar(c);
267 static inline ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size)
269 if (semihosting_is_redirected(semihosting, fd))
270 return semihosting_redirect_read(semihosting, buf, size);
272 /* default read */
273 ssize_t result = read(fd, buf, size);
274 if (result == -1)
275 semihosting->sys_errno = errno;
277 return result;
280 static inline int semihosting_getchar(struct semihosting *semihosting, int fd)
282 if (semihosting_is_redirected(semihosting, fd)) {
283 unsigned char c;
285 if (semihosting_redirect_read(semihosting, &c, 1) > 0)
286 return c;
288 return EOF;
291 /* default getchar */
292 return getchar();
296 * User operation parameter string storage buffer. Contains valid data when the
297 * TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running.
299 static char *semihosting_user_op_params;
301 const char *semihosting_opcode_to_str(const uint64_t opcode)
303 switch (opcode) {
304 case SEMIHOSTING_SYS_CLOSE:
305 return "CLOSE";
306 case SEMIHOSTING_SYS_CLOCK:
307 return "CLOCK";
308 case SEMIHOSTING_SYS_ELAPSED:
309 return "ELAPSED";
310 case SEMIHOSTING_SYS_ERRNO:
311 return "ERRNO";
312 case SEMIHOSTING_SYS_EXIT:
313 return "EXIT";
314 case SEMIHOSTING_SYS_EXIT_EXTENDED:
315 return "EXIT_EXTENDED";
316 case SEMIHOSTING_SYS_FLEN:
317 return "FLEN";
318 case SEMIHOSTING_SYS_GET_CMDLINE:
319 return "GET_CMDLINE";
320 case SEMIHOSTING_SYS_HEAPINFO:
321 return "HEAPINFO";
322 case SEMIHOSTING_SYS_ISERROR:
323 return "ISERROR";
324 case SEMIHOSTING_SYS_ISTTY:
325 return "ISTTY";
326 case SEMIHOSTING_SYS_OPEN:
327 return "OPEN";
328 case SEMIHOSTING_SYS_READ:
329 return "READ";
330 case SEMIHOSTING_SYS_READC:
331 return "READC";
332 case SEMIHOSTING_SYS_REMOVE:
333 return "REMOVE";
334 case SEMIHOSTING_SYS_RENAME:
335 return "RENAME";
336 case SEMIHOSTING_SYS_SEEK:
337 return "SEEK";
338 case SEMIHOSTING_SYS_SYSTEM:
339 return "SYSTEM";
340 case SEMIHOSTING_SYS_TICKFREQ:
341 return "TICKFREQ";
342 case SEMIHOSTING_SYS_TIME:
343 return "TIME";
344 case SEMIHOSTING_SYS_TMPNAM:
345 return "TMPNAM";
346 case SEMIHOSTING_SYS_WRITE:
347 return "WRITE";
348 case SEMIHOSTING_SYS_WRITEC:
349 return "WRITEC";
350 case SEMIHOSTING_SYS_WRITE0:
351 return "WRITE0";
352 case SEMIHOSTING_USER_CMD_0X100 ... SEMIHOSTING_USER_CMD_0X1FF:
353 return "USER_CMD";
354 case SEMIHOSTING_ARM_RESERVED_START ... SEMIHOSTING_ARM_RESERVED_END:
355 return "ARM_RESERVED_CMD";
356 default:
357 return "<unknown>";
362 * Portable implementation of ARM semihosting calls.
363 * Performs the currently pending semihosting operation
364 * encoded in target->semihosting.
366 int semihosting_common(struct target *target)
368 struct semihosting *semihosting = target->semihosting;
369 if (!semihosting) {
370 /* Silently ignore if the semihosting field was not set. */
371 return ERROR_OK;
374 struct gdb_fileio_info *fileio_info = target->fileio_info;
377 * By default return an error.
378 * The actual result must be set by each function
380 semihosting->result = -1;
382 /* Most operations are resumable, except the two exit calls. */
383 semihosting->is_resumable = true;
385 int retval;
387 /* Enough space to hold 4 long words. */
388 uint8_t fields[4*8];
390 LOG_DEBUG("op=0x%x (%s), param=0x%" PRIx64, semihosting->op,
391 semihosting_opcode_to_str(semihosting->op),
392 semihosting->param);
394 switch (semihosting->op) {
396 case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
398 * Returns the number of centiseconds (hundredths of a second)
399 * since the execution started.
401 * Values returned can be of limited use for some benchmarking
402 * purposes because of communication overhead or other
403 * agent-specific factors. For example, with a debug hardware
404 * unit the request is passed back to the host for execution.
405 * This can lead to unpredictable delays in transmission and
406 * process scheduling.
408 * Use this function to calculate time intervals, by calculating
409 * differences between intervals with and without the code
410 * sequence to be timed.
412 * Entry
413 * The PARAMETER REGISTER must contain 0. There are no other
414 * parameters.
416 * Return
417 * On exit, the RETURN REGISTER contains:
418 * - The number of centiseconds since some arbitrary start
419 * point, if the call is successful.
420 * - –1 if the call is not successful. For example, because
421 * of a communications error.
424 clock_t delta = clock() - semihosting->setup_time;
426 semihosting->result = delta / (CLOCKS_PER_SEC / 100);
428 break;
430 case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
432 * Closes a file on the host system. The handle must reference
433 * a file that was opened with SYS_OPEN.
435 * Entry
436 * On entry, the PARAMETER REGISTER contains a pointer to a
437 * one-field argument block:
438 * - field 1 Contains a handle for an open file.
440 * Return
441 * On exit, the RETURN REGISTER contains:
442 * - 0 if the call is successful
443 * - –1 if the call is not successful.
445 retval = semihosting_read_fields(target, 1, fields);
446 if (retval != ERROR_OK)
447 return retval;
448 else {
449 int fd = semihosting_get_field(target, 0, fields);
450 /* Do not allow to close OpenOCD's own standard streams */
451 if (fd == 0 || fd == 1 || fd == 2) {
452 LOG_DEBUG("ignoring semihosting attempt to close %s",
453 (fd == 0) ? "stdin" :
454 (fd == 1) ? "stdout" : "stderr");
455 /* Just pretend success */
456 semihosting->result = 0;
457 break;
459 /* Close the descriptor */
460 if (semihosting->is_fileio) {
461 semihosting->hit_fileio = true;
462 fileio_info->identifier = "close";
463 fileio_info->param_1 = fd;
464 } else {
465 semihosting->result = close(fd);
466 if (semihosting->result == -1)
467 semihosting->sys_errno = errno;
468 LOG_DEBUG("close(%d)=%" PRId64, fd, semihosting->result);
471 break;
473 case SEMIHOSTING_SYS_ERRNO: /* 0x13 */
475 * Returns the value of the C library errno variable that is
476 * associated with the semihosting implementation. The errno
477 * variable can be set by a number of C library semihosted
478 * functions, including:
479 * - SYS_REMOVE
480 * - SYS_OPEN
481 * - SYS_CLOSE
482 * - SYS_READ
483 * - SYS_WRITE
484 * - SYS_SEEK.
486 * Whether errno is set or not, and to what value, is entirely
487 * host-specific, except where the ISO C standard defines the
488 * behavior.
490 * Entry
491 * There are no parameters. The PARAMETER REGISTER must be 0.
493 * Return
494 * On exit, the RETURN REGISTER contains the value of the C
495 * library errno variable.
497 semihosting->result = semihosting->sys_errno;
498 break;
500 case SEMIHOSTING_SYS_EXIT: /* 0x18 */
502 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
503 * previous versions of the documentation.
505 * An application calls this operation to report an exception
506 * to the debugger directly. The most common use is to report
507 * that execution has completed, using ADP_Stopped_ApplicationExit.
509 * Note: This semihosting operation provides no means for 32-bit
510 * callers to indicate an application exit with a specified exit
511 * code. Semihosting callers may prefer to check for the presence
512 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
513 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
514 * is available.
516 * Entry (32-bit)
517 * On entry, the PARAMETER register is set to a reason code
518 * describing the cause of the trap. Not all semihosting client
519 * implementations will necessarily trap every corresponding
520 * event. Important reason codes are:
522 * - ADP_Stopped_ApplicationExit 0x20026
523 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
525 * Entry (64-bit)
526 * On entry, the PARAMETER REGISTER contains a pointer to a
527 * two-field argument block:
528 * - field 1 The exception type, which is one of the set of
529 * reason codes in the above tables.
530 * - field 2 A subcode, whose meaning depends on the reason
531 * code in field 1.
532 * In particular, if field 1 is ADP_Stopped_ApplicationExit
533 * then field 2 is an exit status code, as passed to the C
534 * standard library exit() function. A simulator receiving
535 * this request must notify a connected debugger, if present,
536 * and then exit with the specified status.
538 * Return
539 * No return is expected from these calls. However, it is
540 * possible for the debugger to request that the application
541 * continues by performing an RDI_Execute request or equivalent.
542 * In this case, execution continues with the registers as they
543 * were on entry to the operation, or as subsequently modified
544 * by the debugger.
546 if (semihosting->word_size_bytes == 8) {
547 retval = semihosting_read_fields(target, 2, fields);
548 if (retval != ERROR_OK)
549 return retval;
550 else {
551 int type = semihosting_get_field(target, 0, fields);
552 int code = semihosting_get_field(target, 1, fields);
554 if (type == ADP_STOPPED_APPLICATION_EXIT) {
555 if (!gdb_get_actual_connections())
556 exit(code);
557 else {
558 fprintf(stderr,
559 "semihosting: *** application exited with %d ***\n",
560 code);
562 } else {
563 fprintf(stderr,
564 "semihosting: application exception %#x\n",
565 type);
568 } else {
569 if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
570 if (!gdb_get_actual_connections())
571 exit(0);
572 else {
573 fprintf(stderr,
574 "semihosting: *** application exited normally ***\n");
576 } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
577 /* Chosen more or less arbitrarily to have a nicer message,
578 * otherwise all other return the same exit code 1. */
579 if (!gdb_get_actual_connections())
580 exit(1);
581 else {
582 fprintf(stderr,
583 "semihosting: *** application exited with error ***\n");
585 } else {
586 if (!gdb_get_actual_connections())
587 exit(1);
588 else {
589 fprintf(stderr,
590 "semihosting: application exception %#x\n",
591 (unsigned) semihosting->param);
595 if (!semihosting->has_resumable_exit) {
596 semihosting->is_resumable = false;
597 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
599 break;
601 case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
603 * This operation is only supported if the semihosting extension
604 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
605 * reported using feature byte 0, bit 0. If this extension is
606 * supported, then the implementation provides a means to
607 * report a normal exit with a nonzero exit status in both 32-bit
608 * and 64-bit semihosting APIs.
610 * The implementation must provide the semihosting call
611 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
613 * SYS_EXIT_EXTENDED is used by an application to report an
614 * exception or exit to the debugger directly. The most common
615 * use is to report that execution has completed, using
616 * ADP_Stopped_ApplicationExit.
618 * Entry
619 * On entry, the PARAMETER REGISTER contains a pointer to a
620 * two-field argument block:
621 * - field 1 The exception type, which should be one of the set
622 * of reason codes that are documented for the SYS_EXIT
623 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
624 * - field 2 A subcode, whose meaning depends on the reason
625 * code in field 1. In particular, if field 1 is
626 * ADP_Stopped_ApplicationExit then field 2 is an exit status
627 * code, as passed to the C standard library exit() function.
628 * A simulator receiving this request must notify a connected
629 * debugger, if present, and then exit with the specified status.
631 * Return
632 * No return is expected from these calls.
634 * For the A64 API, this call is identical to the behavior of
635 * the mandatory SYS_EXIT (0x18) call. If this extension is
636 * supported, then both calls must be implemented.
638 retval = semihosting_read_fields(target, 2, fields);
639 if (retval != ERROR_OK)
640 return retval;
641 else {
642 int type = semihosting_get_field(target, 0, fields);
643 int code = semihosting_get_field(target, 1, fields);
645 if (type == ADP_STOPPED_APPLICATION_EXIT) {
646 if (!gdb_get_actual_connections())
647 exit(code);
648 else {
649 fprintf(stderr,
650 "semihosting: *** application exited with %d ***\n",
651 code);
653 } else {
654 fprintf(stderr, "semihosting: exception %#x\n",
655 type);
658 if (!semihosting->has_resumable_exit) {
659 semihosting->is_resumable = false;
660 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
662 break;
664 case SEMIHOSTING_SYS_FLEN: /* 0x0C */
666 * Returns the length of a specified file.
668 * Entry
669 * On entry, the PARAMETER REGISTER contains a pointer to a
670 * one-field argument block:
671 * - field 1 A handle for a previously opened, seekable file
672 * object.
674 * Return
675 * On exit, the RETURN REGISTER contains:
676 * - The current length of the file object, if the call is
677 * successful.
678 * - –1 if an error occurs.
680 if (semihosting->is_fileio) {
681 semihosting->result = -1;
682 semihosting->sys_errno = EINVAL;
684 retval = semihosting_read_fields(target, 1, fields);
685 if (retval != ERROR_OK)
686 return retval;
687 else {
688 int fd = semihosting_get_field(target, 0, fields);
689 struct stat buf;
690 semihosting->result = fstat(fd, &buf);
691 if (semihosting->result == -1) {
692 semihosting->sys_errno = errno;
693 LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
694 break;
696 LOG_DEBUG("fstat(%d)=%" PRId64, fd, semihosting->result);
697 semihosting->result = buf.st_size;
699 break;
701 case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
703 * Returns the command line that is used for the call to the
704 * executable, that is, argc and argv.
706 * Entry
707 * On entry, the PARAMETER REGISTER points to a two-field data
708 * block to be used for returning the command string and its length:
709 * - field 1 A pointer to a buffer of at least the size that is
710 * specified in field 2.
711 * - field 2 The length of the buffer in bytes.
713 * Return
714 * On exit:
715 * If the call is successful, then the RETURN REGISTER contains 0,
716 * the PARAMETER REGISTER is unchanged, and the data block is
717 * updated as follows:
718 * - field 1 A pointer to a null-terminated string of the command
719 * line.
720 * - field 2 The length of the string in bytes.
721 * If the call is not successful, then the RETURN REGISTER
722 * contains -1.
724 * Note: The semihosting implementation might impose limits on
725 * the maximum length of the string that can be transferred.
726 * However, the implementation must be able to support a
727 * command-line length of at least 80 bytes.
729 retval = semihosting_read_fields(target, 2, fields);
730 if (retval != ERROR_OK)
731 return retval;
732 else {
733 uint64_t addr = semihosting_get_field(target, 0, fields);
734 size_t size = semihosting_get_field(target, 1, fields);
736 char *arg = semihosting->cmdline ?
737 semihosting->cmdline : "";
738 uint32_t len = strlen(arg) + 1;
739 if (len > size)
740 semihosting->result = -1;
741 else {
742 semihosting_set_field(target, len, 1, fields);
743 retval = target_write_buffer(target, addr, len,
744 (uint8_t *)arg);
745 if (retval != ERROR_OK)
746 return retval;
747 semihosting->result = 0;
749 retval = semihosting_write_fields(target, 2, fields);
750 if (retval != ERROR_OK)
751 return retval;
753 LOG_DEBUG("SYS_GET_CMDLINE=[%s], %" PRId64, arg, semihosting->result);
755 break;
757 case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
759 * Returns the system stack and heap parameters.
761 * Entry
762 * On entry, the PARAMETER REGISTER contains the address of a
763 * pointer to a four-field data block. The contents of the data
764 * block are filled by the function. The following C-like
765 * pseudocode describes the layout of the block:
766 * struct block {
767 * void* heap_base;
768 * void* heap_limit;
769 * void* stack_base;
770 * void* stack_limit;
771 * };
773 * Return
774 * On exit, the PARAMETER REGISTER is unchanged and the data
775 * block has been updated.
777 retval = semihosting_read_fields(target, 1, fields);
778 if (retval != ERROR_OK)
779 return retval;
780 else {
781 uint64_t addr = semihosting_get_field(target, 0, fields);
782 /* tell the remote we have no idea */
783 memset(fields, 0, 4 * semihosting->word_size_bytes);
784 retval = target_write_memory(target, addr, 4,
785 semihosting->word_size_bytes,
786 fields);
787 if (retval != ERROR_OK)
788 return retval;
789 semihosting->result = 0;
791 break;
793 case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
795 * Determines whether the return code from another semihosting
796 * call is an error status or not.
798 * This call is passed a parameter block containing the error
799 * code to examine.
801 * Entry
802 * On entry, the PARAMETER REGISTER contains a pointer to a
803 * one-field data block:
804 * - field 1 The required status word to check.
806 * Return
807 * On exit, the RETURN REGISTER contains:
808 * - 0 if the status field is not an error indication
809 * - A nonzero value if the status field is an error indication.
811 retval = semihosting_read_fields(target, 1, fields);
812 if (retval != ERROR_OK)
813 return retval;
815 uint64_t code = semihosting_get_field(target, 0, fields);
816 semihosting->result = (code != 0);
817 break;
819 case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
821 * Checks whether a file is connected to an interactive device.
823 * Entry
824 * On entry, the PARAMETER REGISTER contains a pointer to a
825 * one-field argument block:
826 * field 1 A handle for a previously opened file object.
828 * Return
829 * On exit, the RETURN REGISTER contains:
830 * - 1 if the handle identifies an interactive device.
831 * - 0 if the handle identifies a file.
832 * - A value other than 1 or 0 if an error occurs.
834 if (semihosting->is_fileio) {
835 semihosting->hit_fileio = true;
836 fileio_info->identifier = "isatty";
837 fileio_info->param_1 = semihosting->param;
838 } else {
839 retval = semihosting_read_fields(target, 1, fields);
840 if (retval != ERROR_OK)
841 return retval;
842 int fd = semihosting_get_field(target, 0, fields);
843 // isatty() on Windows may return any non-zero value if fd is a terminal
844 semihosting->result = isatty(fd) ? 1 : 0;
845 if (semihosting->result == 0)
846 semihosting->sys_errno = errno;
847 LOG_DEBUG("isatty(%d)=%" PRId64, fd, semihosting->result);
849 break;
851 case SEMIHOSTING_SYS_OPEN: /* 0x01 */
853 * Opens a file on the host system.
855 * The file path is specified either as relative to the current
856 * directory of the host process, or absolute, using the path
857 * conventions of the host operating system.
859 * Semihosting implementations must support opening the special
860 * path name :semihosting-features as part of the semihosting
861 * extensions reporting mechanism.
863 * ARM targets interpret the special path name :tt as meaning
864 * the console input stream, for an open-read or the console
865 * output stream, for an open-write. Opening these streams is
866 * performed as part of the standard startup code for those
867 * applications that reference the C stdio streams. The
868 * semihosting extension SH_EXT_STDOUT_STDERR allows the
869 * semihosting caller to open separate output streams
870 * corresponding to stdout and stderr. This extension is
871 * reported using feature byte 0, bit 1. Use SYS_OPEN with
872 * the special path name :semihosting-features to access the
873 * feature bits.
875 * If this extension is supported, the implementation must
876 * support the following additional semantics to SYS_OPEN:
877 * - If the special path name :tt is opened with an fopen
878 * mode requesting write access (w, wb, w+, or w+b), then
879 * this is a request to open stdout.
880 * - If the special path name :tt is opened with a mode
881 * requesting append access (a, ab, a+, or a+b), then this is
882 * a request to open stderr.
884 * Entry
885 * On entry, the PARAMETER REGISTER contains a pointer to a
886 * three-field argument block:
887 * - field 1 A pointer to a null-terminated string containing
888 * a file or device name.
889 * - field 2 An integer that specifies the file opening mode.
890 * - field 3 An integer that gives the length of the string
891 * pointed to by field 1.
893 * The length does not include the terminating null character
894 * that must be present.
896 * Return
897 * On exit, the RETURN REGISTER contains:
898 * - A nonzero handle if the call is successful.
899 * - –1 if the call is not successful.
901 retval = semihosting_read_fields(target, 3, fields);
902 if (retval != ERROR_OK)
903 return retval;
904 else {
905 uint64_t addr = semihosting_get_field(target, 0, fields);
906 uint32_t mode = semihosting_get_field(target, 1, fields);
907 size_t len = semihosting_get_field(target, 2, fields);
909 if (mode > 11) {
910 semihosting->result = -1;
911 semihosting->sys_errno = EINVAL;
912 break;
914 size_t basedir_len = semihosting->basedir ? strlen(semihosting->basedir) : 0;
915 uint8_t *fn = malloc(basedir_len + len + 2);
916 if (!fn) {
917 semihosting->result = -1;
918 semihosting->sys_errno = ENOMEM;
919 } else {
920 if (basedir_len > 0) {
921 strcpy((char *)fn, semihosting->basedir);
922 if (fn[basedir_len - 1] != '/')
923 fn[basedir_len++] = '/';
925 retval = target_read_memory(target, addr, 1, len, fn + basedir_len);
926 if (retval != ERROR_OK) {
927 free(fn);
928 return retval;
930 fn[basedir_len + len] = 0;
931 /* TODO: implement the :semihosting-features special file.
932 * */
933 if (semihosting->is_fileio) {
934 if (strcmp((char *)fn, ":semihosting-features") == 0) {
935 semihosting->result = -1;
936 semihosting->sys_errno = EINVAL;
937 } else if (strcmp((char *)fn, ":tt") == 0) {
938 if (mode == 0) {
939 semihosting->result = 0;
940 } else if (mode == 4) {
941 semihosting->result = 1;
942 } else if (mode == 8) {
943 semihosting->result = 2;
944 } else {
945 semihosting->result = -1;
946 semihosting->sys_errno = EINVAL;
948 } else {
949 semihosting->hit_fileio = true;
950 fileio_info->identifier = "open";
951 fileio_info->param_1 = addr;
952 fileio_info->param_2 = len;
953 fileio_info->param_3 = open_gdb_modeflags[mode];
954 fileio_info->param_4 = 0644;
956 } else {
957 if (strcmp((char *)fn, ":tt") == 0) {
958 /* Mode is:
959 * - 0-3 ("r") for stdin,
960 * - 4-7 ("w") for stdout,
961 * - 8-11 ("a") for stderr */
962 int fd;
963 if (mode < 4) {
964 fd = dup(STDIN_FILENO);
965 semihosting->stdin_fd = fd;
966 LOG_DEBUG("dup(STDIN)=%d", fd);
967 } else if (mode < 8) {
968 fd = dup(STDOUT_FILENO);
969 semihosting->stdout_fd = fd;
970 LOG_DEBUG("dup(STDOUT)=%d", fd);
971 } else {
972 fd = dup(STDERR_FILENO);
973 semihosting->stderr_fd = fd;
974 LOG_DEBUG("dup(STDERR)=%d", fd);
976 semihosting->result = fd;
977 if (fd == -1)
978 semihosting->sys_errno = errno;
979 } else {
980 /* cygwin requires the permission setting
981 * otherwise it will fail to reopen a previously
982 * written file */
983 semihosting->result = open((char *)fn,
984 open_host_modeflags[mode],
985 0644);
986 if (semihosting->result == -1)
987 semihosting->sys_errno = errno;
988 LOG_DEBUG("open('%s')=%" PRId64, fn, semihosting->result);
991 free(fn);
994 break;
996 case SEMIHOSTING_SYS_READ: /* 0x06 */
998 * Reads the contents of a file into a buffer. The file position
999 * is specified either:
1000 * - Explicitly by a SYS_SEEK.
1001 * - Implicitly one byte beyond the previous SYS_READ or
1002 * SYS_WRITE request.
1004 * The file position is at the start of the file when it is
1005 * opened, and is lost when the file is closed. Perform the
1006 * file operation as a single action whenever possible. For
1007 * example, do not split a read of 16KB into four 4KB chunks
1008 * unless there is no alternative.
1010 * Entry
1011 * On entry, the PARAMETER REGISTER contains a pointer to a
1012 * three-field data block:
1013 * - field 1 Contains a handle for a file previously opened
1014 * with SYS_OPEN.
1015 * - field 2 Points to a buffer.
1016 * - field 3 Contains the number of bytes to read to the buffer
1017 * from the file.
1019 * Return
1020 * On exit, the RETURN REGISTER contains the number of bytes not
1021 * filled in the buffer (buffer_length - bytes_read) as follows:
1022 * - If the RETURN REGISTER is 0, the entire buffer was
1023 * successfully filled.
1024 * - If the RETURN REGISTER is the same as field 3, no bytes
1025 * were read (EOF can be assumed).
1026 * - If the RETURN REGISTER contains a value smaller than
1027 * field 3, the read succeeded but the buffer was only partly
1028 * filled. For interactive devices, this is the most common
1029 * return value.
1031 retval = semihosting_read_fields(target, 3, fields);
1032 if (retval != ERROR_OK)
1033 return retval;
1034 else {
1035 int fd = semihosting_get_field(target, 0, fields);
1036 uint64_t addr = semihosting_get_field(target, 1, fields);
1037 size_t len = semihosting_get_field(target, 2, fields);
1038 if (semihosting->is_fileio) {
1039 semihosting->hit_fileio = true;
1040 fileio_info->identifier = "read";
1041 fileio_info->param_1 = fd;
1042 fileio_info->param_2 = addr;
1043 fileio_info->param_3 = len;
1044 } else {
1045 uint8_t *buf = malloc(len);
1046 if (!buf) {
1047 semihosting->result = -1;
1048 semihosting->sys_errno = ENOMEM;
1049 } else {
1050 semihosting->result = semihosting_read(semihosting, fd, buf, len);
1051 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1053 addr,
1054 len,
1055 semihosting->result);
1056 if (semihosting->result >= 0) {
1057 retval = target_write_buffer(target, addr,
1058 semihosting->result,
1059 buf);
1060 if (retval != ERROR_OK) {
1061 free(buf);
1062 return retval;
1064 /* the number of bytes NOT filled in */
1065 semihosting->result = len -
1066 semihosting->result;
1068 free(buf);
1072 break;
1074 case SEMIHOSTING_SYS_READC: /* 0x07 */
1076 * Reads a byte from the console.
1078 * Entry
1079 * The PARAMETER REGISTER must contain 0. There are no other
1080 * parameters or values possible.
1082 * Return
1083 * On exit, the RETURN REGISTER contains the byte read from
1084 * the console.
1086 if (semihosting->is_fileio) {
1087 LOG_ERROR("SYS_READC not supported by semihosting fileio");
1088 return ERROR_FAIL;
1090 semihosting->result = semihosting_getchar(semihosting, semihosting->stdin_fd);
1091 LOG_DEBUG("getchar()=%" PRId64, semihosting->result);
1092 break;
1094 case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
1096 * Deletes a specified file on the host filing system.
1098 * Entry
1099 * On entry, the PARAMETER REGISTER contains a pointer to a
1100 * two-field argument block:
1101 * - field 1 Points to a null-terminated string that gives the
1102 * path name of the file to be deleted.
1103 * - field 2 The length of the string.
1105 * Return
1106 * On exit, the RETURN REGISTER contains:
1107 * - 0 if the delete is successful
1108 * - A nonzero, host-specific error code if the delete fails.
1110 retval = semihosting_read_fields(target, 2, fields);
1111 if (retval != ERROR_OK)
1112 return retval;
1113 else {
1114 uint64_t addr = semihosting_get_field(target, 0, fields);
1115 size_t len = semihosting_get_field(target, 1, fields);
1116 if (semihosting->is_fileio) {
1117 semihosting->hit_fileio = true;
1118 fileio_info->identifier = "unlink";
1119 fileio_info->param_1 = addr;
1120 fileio_info->param_2 = len;
1121 } else {
1122 uint8_t *fn = malloc(len+1);
1123 if (!fn) {
1124 semihosting->result = -1;
1125 semihosting->sys_errno = ENOMEM;
1126 } else {
1127 retval =
1128 target_read_memory(target, addr, 1, len,
1129 fn);
1130 if (retval != ERROR_OK) {
1131 free(fn);
1132 return retval;
1134 fn[len] = 0;
1135 semihosting->result = remove((char *)fn);
1136 if (semihosting->result == -1)
1137 semihosting->sys_errno = errno;
1138 LOG_DEBUG("remove('%s')=%" PRId64, fn, semihosting->result);
1140 free(fn);
1144 break;
1146 case SEMIHOSTING_SYS_RENAME: /* 0x0F */
1148 * Renames a specified file.
1150 * Entry
1151 * On entry, the PARAMETER REGISTER contains a pointer to a
1152 * four-field data block:
1153 * - field 1 A pointer to the name of the old file.
1154 * - field 2 The length of the old filename.
1155 * - field 3 A pointer to the new filename.
1156 * - field 4 The length of the new filename. Both strings are
1157 * null-terminated.
1159 * Return
1160 * On exit, the RETURN REGISTER contains:
1161 * - 0 if the rename is successful.
1162 * - A nonzero, host-specific error code if the rename fails.
1164 retval = semihosting_read_fields(target, 4, fields);
1165 if (retval != ERROR_OK)
1166 return retval;
1167 else {
1168 uint64_t addr1 = semihosting_get_field(target, 0, fields);
1169 size_t len1 = semihosting_get_field(target, 1, fields);
1170 uint64_t addr2 = semihosting_get_field(target, 2, fields);
1171 size_t len2 = semihosting_get_field(target, 3, fields);
1172 if (semihosting->is_fileio) {
1173 semihosting->hit_fileio = true;
1174 fileio_info->identifier = "rename";
1175 fileio_info->param_1 = addr1;
1176 fileio_info->param_2 = len1;
1177 fileio_info->param_3 = addr2;
1178 fileio_info->param_4 = len2;
1179 } else {
1180 uint8_t *fn1 = malloc(len1+1);
1181 uint8_t *fn2 = malloc(len2+1);
1182 if (!fn1 || !fn2) {
1183 free(fn1);
1184 free(fn2);
1185 semihosting->result = -1;
1186 semihosting->sys_errno = ENOMEM;
1187 } else {
1188 retval = target_read_memory(target, addr1, 1, len1,
1189 fn1);
1190 if (retval != ERROR_OK) {
1191 free(fn1);
1192 free(fn2);
1193 return retval;
1195 retval = target_read_memory(target, addr2, 1, len2,
1196 fn2);
1197 if (retval != ERROR_OK) {
1198 free(fn1);
1199 free(fn2);
1200 return retval;
1202 fn1[len1] = 0;
1203 fn2[len2] = 0;
1204 semihosting->result = rename((char *)fn1,
1205 (char *)fn2);
1206 // rename() on Windows returns nonzero on error
1207 if (semihosting->result != 0)
1208 semihosting->sys_errno = errno;
1209 LOG_DEBUG("rename('%s', '%s')=%" PRId64 " %d", fn1, fn2, semihosting->result, errno);
1210 free(fn1);
1211 free(fn2);
1215 break;
1217 case SEMIHOSTING_SYS_SEEK: /* 0x0A */
1219 * Seeks to a specified position in a file using an offset
1220 * specified from the start of the file. The file is assumed
1221 * to be a byte array and the offset is given in bytes.
1223 * Entry
1224 * On entry, the PARAMETER REGISTER contains a pointer to a
1225 * two-field data block:
1226 * - field 1 A handle for a seekable file object.
1227 * - field 2 The absolute byte position to seek to.
1229 * Return
1230 * On exit, the RETURN REGISTER contains:
1231 * - 0 if the request is successful.
1232 * - A negative value if the request is not successful.
1233 * Use SYS_ERRNO to read the value of the host errno variable
1234 * describing the error.
1236 * Note: The effect of seeking outside the current extent of
1237 * the file object is undefined.
1239 retval = semihosting_read_fields(target, 2, fields);
1240 if (retval != ERROR_OK)
1241 return retval;
1242 else {
1243 int fd = semihosting_get_field(target, 0, fields);
1244 off_t pos = semihosting_get_field(target, 1, fields);
1245 if (semihosting->is_fileio) {
1246 semihosting->hit_fileio = true;
1247 fileio_info->identifier = "lseek";
1248 fileio_info->param_1 = fd;
1249 fileio_info->param_2 = pos;
1250 fileio_info->param_3 = SEEK_SET;
1251 } else {
1252 semihosting->result = lseek(fd, pos, SEEK_SET);
1253 if (semihosting->result == -1)
1254 semihosting->sys_errno = errno;
1255 LOG_DEBUG("lseek(%d, %d)=%" PRId64, fd, (int)pos, semihosting->result);
1256 if (semihosting->result == pos)
1257 semihosting->result = 0;
1260 break;
1262 case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1264 * Passes a command to the host command-line interpreter.
1265 * This enables you to execute a system command such as dir,
1266 * ls, or pwd. The terminal I/O is on the host, and is not
1267 * visible to the target.
1269 * Entry
1270 * On entry, the PARAMETER REGISTER contains a pointer to a
1271 * two-field argument block:
1272 * - field 1 Points to a string to be passed to the host
1273 * command-line interpreter.
1274 * - field 2 The length of the string.
1276 * Return
1277 * On exit, the RETURN REGISTER contains the return status.
1280 /* Provide SYS_SYSTEM functionality. Uses the
1281 * libc system command, there may be a reason *NOT*
1282 * to use this, but as I can't think of one, I
1283 * implemented it this way.
1285 retval = semihosting_read_fields(target, 2, fields);
1286 if (retval != ERROR_OK)
1287 return retval;
1288 else {
1289 uint64_t addr = semihosting_get_field(target, 0, fields);
1290 size_t len = semihosting_get_field(target, 1, fields);
1291 if (semihosting->is_fileio) {
1292 semihosting->hit_fileio = true;
1293 fileio_info->identifier = "system";
1294 fileio_info->param_1 = addr;
1295 fileio_info->param_2 = len;
1296 } else {
1297 uint8_t *cmd = malloc(len+1);
1298 if (!cmd) {
1299 semihosting->result = -1;
1300 semihosting->sys_errno = ENOMEM;
1301 } else {
1302 retval = target_read_memory(target,
1303 addr,
1305 len,
1306 cmd);
1307 if (retval != ERROR_OK) {
1308 free(cmd);
1309 return retval;
1310 } else {
1311 cmd[len] = 0;
1312 semihosting->result = system(
1313 (const char *)cmd);
1314 LOG_DEBUG("system('%s')=%" PRId64, cmd, semihosting->result);
1317 free(cmd);
1321 break;
1323 case SEMIHOSTING_SYS_TIME: /* 0x11 */
1325 * Returns the number of seconds since 00:00 January 1, 1970.
1326 * This value is real-world time, regardless of any debug agent
1327 * configuration.
1329 * Entry
1330 * There are no parameters.
1332 * Return
1333 * On exit, the RETURN REGISTER contains the number of seconds.
1335 semihosting->result = time(NULL);
1336 break;
1338 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1340 * Writes the contents of a buffer to a specified file at the
1341 * current file position. The file position is specified either:
1342 * - Explicitly, by a SYS_SEEK.
1343 * - Implicitly as one byte beyond the previous SYS_READ or
1344 * SYS_WRITE request.
1346 * The file position is at the start of the file when the file
1347 * is opened, and is lost when the file is closed.
1349 * Perform the file operation as a single action whenever
1350 * possible. For example, do not split a write of 16KB into
1351 * four 4KB chunks unless there is no alternative.
1353 * Entry
1354 * On entry, the PARAMETER REGISTER contains a pointer to a
1355 * three-field data block:
1356 * - field 1 Contains a handle for a file previously opened
1357 * with SYS_OPEN.
1358 * - field 2 Points to the memory containing the data to be written.
1359 * - field 3 Contains the number of bytes to be written from
1360 * the buffer to the file.
1362 * Return
1363 * On exit, the RETURN REGISTER contains:
1364 * - 0 if the call is successful.
1365 * - The number of bytes that are not written, if there is an error.
1367 retval = semihosting_read_fields(target, 3, fields);
1368 if (retval != ERROR_OK)
1369 return retval;
1370 else {
1371 int fd = semihosting_get_field(target, 0, fields);
1372 uint64_t addr = semihosting_get_field(target, 1, fields);
1373 size_t len = semihosting_get_field(target, 2, fields);
1374 if (semihosting->is_fileio) {
1375 semihosting->hit_fileio = true;
1376 fileio_info->identifier = "write";
1377 fileio_info->param_1 = fd;
1378 fileio_info->param_2 = addr;
1379 fileio_info->param_3 = len;
1380 } else {
1381 uint8_t *buf = malloc(len);
1382 if (!buf) {
1383 semihosting->result = -1;
1384 semihosting->sys_errno = ENOMEM;
1385 } else {
1386 retval = target_read_buffer(target, addr, len, buf);
1387 if (retval != ERROR_OK) {
1388 free(buf);
1389 return retval;
1391 semihosting->result = semihosting_write(semihosting, fd, buf, len);
1392 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%" PRId64,
1394 addr,
1395 len,
1396 semihosting->result);
1397 if (semihosting->result >= 0) {
1398 /* The number of bytes that are NOT written.
1399 * */
1400 semihosting->result = len -
1401 semihosting->result;
1404 free(buf);
1408 break;
1410 case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1412 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1413 * to the debug channel. When executed under a semihosting
1414 * debugger, the character appears on the host debugger console.
1416 * Entry
1417 * On entry, the PARAMETER REGISTER contains a pointer to the
1418 * character.
1420 * Return
1421 * None. The RETURN REGISTER is corrupted.
1423 if (semihosting->is_fileio) {
1424 semihosting->hit_fileio = true;
1425 fileio_info->identifier = "write";
1426 fileio_info->param_1 = 1;
1427 fileio_info->param_2 = semihosting->param;
1428 fileio_info->param_3 = 1;
1429 } else {
1430 uint64_t addr = semihosting->param;
1431 unsigned char c;
1432 retval = target_read_memory(target, addr, 1, 1, &c);
1433 if (retval != ERROR_OK)
1434 return retval;
1435 semihosting_putchar(semihosting, semihosting->stdout_fd, c);
1436 semihosting->result = 0;
1438 break;
1440 case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1442 * Writes a null-terminated string to the debug channel.
1443 * When executed under a semihosting debugger, the characters
1444 * appear on the host debugger console.
1446 * Entry
1447 * On entry, the PARAMETER REGISTER contains a pointer to the
1448 * first byte of the string.
1450 * Return
1451 * None. The RETURN REGISTER is corrupted.
1453 if (semihosting->is_fileio) {
1454 size_t count = 0;
1455 uint64_t addr = semihosting->param;
1456 for (;; addr++) {
1457 unsigned char c;
1458 retval = target_read_memory(target, addr, 1, 1, &c);
1459 if (retval != ERROR_OK)
1460 return retval;
1461 if (c == '\0')
1462 break;
1463 count++;
1465 semihosting->hit_fileio = true;
1466 fileio_info->identifier = "write";
1467 fileio_info->param_1 = 1;
1468 fileio_info->param_2 = semihosting->param;
1469 fileio_info->param_3 = count;
1470 } else {
1471 uint64_t addr = semihosting->param;
1472 do {
1473 unsigned char c;
1474 retval = target_read_memory(target, addr++, 1, 1, &c);
1475 if (retval != ERROR_OK)
1476 return retval;
1477 if (!c)
1478 break;
1479 semihosting_putchar(semihosting, semihosting->stdout_fd, c);
1480 } while (1);
1481 semihosting->result = 0;
1483 break;
1485 case SEMIHOSTING_USER_CMD_0X100 ... SEMIHOSTING_USER_CMD_0X107:
1487 * This is a user defined operation (while user cmds 0x100-0x1ff
1488 * are possible, only 0x100-0x107 are currently implemented).
1490 * Reads the user operation parameters from target, then fires the
1491 * corresponding target event. When the target callbacks returned,
1492 * cleans up the command parameter buffer.
1494 * Entry
1495 * On entry, the PARAMETER REGISTER contains a pointer to a
1496 * two-field data block:
1497 * - field 1 Contains a pointer to the bound command parameter
1498 * string
1499 * - field 2 Contains the command parameter string length
1501 * Return
1502 * On exit, the RETURN REGISTER contains the return status.
1504 if (semihosting->user_command_extension) {
1505 retval = semihosting->user_command_extension(target);
1506 if (retval != ERROR_NOT_IMPLEMENTED)
1507 break;
1508 /* If custom user command not handled, we are looking for the TCL handler */
1511 assert(!semihosting_user_op_params);
1512 retval = semihosting_read_fields(target, 2, fields);
1513 if (retval != ERROR_OK) {
1514 LOG_ERROR("Failed to read fields for user defined command"
1515 " op=0x%x", semihosting->op);
1516 return retval;
1519 uint64_t addr = semihosting_get_field(target, 0, fields);
1521 size_t len = semihosting_get_field(target, 1, fields);
1522 if (len > SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH) {
1523 LOG_ERROR("The maximum length for user defined command "
1524 "parameter is %u, received length is %zu (op=0x%x)",
1525 SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH,
1526 len,
1527 semihosting->op);
1528 return ERROR_FAIL;
1531 semihosting_user_op_params = malloc(len + 1);
1532 if (!semihosting_user_op_params)
1533 return ERROR_FAIL;
1534 semihosting_user_op_params[len] = 0;
1536 retval = target_read_buffer(target, addr, len,
1537 (uint8_t *)(semihosting_user_op_params));
1538 if (retval != ERROR_OK) {
1539 LOG_ERROR("Failed to read from target, semihosting op=0x%x (%s)",
1540 semihosting->op,
1541 semihosting_opcode_to_str(semihosting->op));
1542 free(semihosting_user_op_params);
1543 semihosting_user_op_params = NULL;
1544 return retval;
1547 target_handle_event(target, semihosting->op);
1548 free(semihosting_user_op_params);
1549 semihosting_user_op_params = NULL;
1550 semihosting->result = 0;
1551 break;
1553 case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1555 * Returns the number of elapsed target ticks since execution
1556 * started.
1557 * Use SYS_TICKFREQ to determine the tick frequency.
1559 * Entry (32-bit)
1560 * On entry, the PARAMETER REGISTER points to a two-field data
1561 * block to be used for returning the number of elapsed ticks:
1562 * - field 1 The least significant field and is at the low address.
1563 * - field 2 The most significant field and is at the high address.
1565 * Entry (64-bit)
1566 * On entry the PARAMETER REGISTER points to a one-field data
1567 * block to be used for returning the number of elapsed ticks:
1568 * - field 1 The number of elapsed ticks as a 64-bit value.
1570 * Return
1571 * On exit:
1572 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1573 * REGISTER is unchanged, and the data block pointed to by the
1574 * PARAMETER REGISTER is filled in with the number of elapsed
1575 * ticks.
1576 * - On failure, the RETURN REGISTER contains -1, and the
1577 * PARAMETER REGISTER contains -1.
1579 * Note: Some semihosting implementations might not support this
1580 * semihosting operation, and they always return -1 in the
1581 * RETURN REGISTER.
1584 case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1586 * Returns the tick frequency.
1588 * Entry
1589 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1591 * Return
1592 * On exit, the RETURN REGISTER contains either:
1593 * - The number of ticks per second.
1594 * - –1 if the target does not know the value of one tick.
1596 * Note: Some semihosting implementations might not support
1597 * this semihosting operation, and they always return -1 in the
1598 * RETURN REGISTER.
1601 case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1603 * Returns a temporary name for a file identified by a system
1604 * file identifier.
1606 * Entry
1607 * On entry, the PARAMETER REGISTER contains a pointer to a
1608 * three-word argument block:
1609 * - field 1 A pointer to a buffer.
1610 * - field 2 A target identifier for this filename. Its value
1611 * must be an integer in the range 0-255.
1612 * - field 3 Contains the length of the buffer. The length must
1613 * be at least the value of L_tmpnam on the host system.
1615 * Return
1616 * On exit, the RETURN REGISTER contains:
1617 * - 0 if the call is successful.
1618 * - –1 if an error occurs.
1620 * The buffer pointed to by the PARAMETER REGISTER contains
1621 * the filename, prefixed with a suitable directory name.
1622 * If you use the same target identifier again, the same
1623 * filename is returned.
1625 * Note: The returned string must be null-terminated.
1628 default:
1629 fprintf(stderr, "semihosting: unsupported call %#x\n",
1630 (unsigned) semihosting->op);
1631 semihosting->result = -1;
1632 semihosting->sys_errno = ENOTSUP;
1635 if (!semihosting->hit_fileio) {
1636 retval = semihosting->post_result(target);
1637 if (retval != ERROR_OK) {
1638 LOG_ERROR("Failed to post semihosting result");
1639 return retval;
1643 return ERROR_OK;
1646 /* -------------------------------------------------------------------------
1647 * Local functions. */
1649 static int semihosting_common_fileio_info(struct target *target,
1650 struct gdb_fileio_info *fileio_info)
1652 struct semihosting *semihosting = target->semihosting;
1653 if (!semihosting)
1654 return ERROR_FAIL;
1657 * To avoid unnecessary duplication, semihosting prepares the
1658 * fileio_info structure out-of-band when the target halts. See
1659 * do_semihosting for more detail.
1661 if (!semihosting->is_fileio || !semihosting->hit_fileio)
1662 return ERROR_FAIL;
1664 return ERROR_OK;
1667 static int semihosting_common_fileio_end(struct target *target, int result,
1668 int fileio_errno, bool ctrl_c)
1670 struct gdb_fileio_info *fileio_info = target->fileio_info;
1671 struct semihosting *semihosting = target->semihosting;
1672 if (!semihosting)
1673 return ERROR_FAIL;
1675 /* clear pending status */
1676 semihosting->hit_fileio = false;
1678 semihosting->result = result;
1681 * Some fileio results do not match up with what the semihosting
1682 * operation expects; for these operations, we munge the results
1683 * below:
1685 switch (semihosting->op) {
1686 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1687 case SEMIHOSTING_SYS_READ: /* 0x06 */
1688 if (result < 0)
1689 semihosting->result = fileio_info->param_3; /* Zero bytes read/written. */
1690 else
1691 semihosting->result = (int64_t)fileio_info->param_3 - result;
1692 break;
1694 case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1695 if (result > 0)
1696 semihosting->result = 0;
1697 break;
1700 bool fileio_failed = false;
1701 if (semihosting->op == SEMIHOSTING_SYS_ISTTY)
1702 fileio_failed = (semihosting->result == 0);
1703 else if (semihosting->op == SEMIHOSTING_SYS_RENAME)
1704 fileio_failed = (semihosting->result != 0);
1705 else
1706 fileio_failed = (semihosting->result == -1);
1708 if (fileio_failed)
1709 semihosting->sys_errno = fileio_errno;
1711 return semihosting->post_result(target);
1714 /* -------------------------------------------------------------------------
1715 * Utility functions. */
1718 * Read all fields of a command from target to buffer.
1720 int semihosting_read_fields(struct target *target, size_t number,
1721 uint8_t *fields)
1723 struct semihosting *semihosting = target->semihosting;
1724 /* Use 4-byte multiples to trigger fast memory access. */
1725 return target_read_memory(target, semihosting->param, 4,
1726 number * (semihosting->word_size_bytes / 4), fields);
1730 * Write all fields of a command from buffer to target.
1732 int semihosting_write_fields(struct target *target, size_t number,
1733 uint8_t *fields)
1735 struct semihosting *semihosting = target->semihosting;
1736 /* Use 4-byte multiples to trigger fast memory access. */
1737 return target_write_memory(target, semihosting->param, 4,
1738 number * (semihosting->word_size_bytes / 4), fields);
1742 * Extract a field from the buffer, considering register size and endianness.
1744 uint64_t semihosting_get_field(struct target *target, size_t index,
1745 uint8_t *fields)
1747 struct semihosting *semihosting = target->semihosting;
1748 if (semihosting->word_size_bytes == 8)
1749 return target_buffer_get_u64(target, fields + (index * 8));
1750 else
1751 return target_buffer_get_u32(target, fields + (index * 4));
1755 * Store a field in the buffer, considering register size and endianness.
1757 void semihosting_set_field(struct target *target, uint64_t value,
1758 size_t index,
1759 uint8_t *fields)
1761 struct semihosting *semihosting = target->semihosting;
1762 if (semihosting->word_size_bytes == 8)
1763 target_buffer_set_u64(target, fields + (index * 8), value);
1764 else
1765 target_buffer_set_u32(target, fields + (index * 4), value);
1768 /* -------------------------------------------------------------------------
1769 * Semihosting redirect over TCP structs and functions */
1771 static int semihosting_service_new_connection_handler(struct connection *connection)
1773 struct semihosting_tcp_service *service = connection->service->priv;
1774 service->semihosting->tcp_connection = connection;
1776 return ERROR_OK;
1779 static int semihosting_service_input_handler(struct connection *connection)
1781 struct semihosting_tcp_service *service = connection->service->priv;
1783 if (!connection->input_pending) {
1784 /* consume received data, not for semihosting IO */
1785 const int buf_len = 100;
1786 char buf[buf_len];
1787 int bytes_read = connection_read(connection, buf, buf_len);
1789 if (bytes_read == 0) {
1790 return ERROR_SERVER_REMOTE_CLOSED;
1791 } else if (bytes_read == -1) {
1792 LOG_ERROR("error during read: %s", strerror(errno));
1793 return ERROR_SERVER_REMOTE_CLOSED;
1795 } else if (service->error != ERROR_OK) {
1796 return ERROR_SERVER_REMOTE_CLOSED;
1799 return ERROR_OK;
1802 static int semihosting_service_connection_closed_handler(struct connection *connection)
1804 struct semihosting_tcp_service *service = connection->service->priv;
1805 if (service)
1806 free(service->name);
1808 return ERROR_OK;
1811 static void semihosting_tcp_close_cnx(struct semihosting *semihosting)
1813 if (!semihosting->tcp_connection)
1814 return;
1816 struct service *service = semihosting->tcp_connection->service;
1817 remove_service(service->name, service->port);
1818 semihosting->tcp_connection = NULL;
1822 static const struct service_driver semihosting_service_driver = {
1823 .name = "semihosting",
1824 .new_connection_during_keep_alive_handler = NULL,
1825 .new_connection_handler = semihosting_service_new_connection_handler,
1826 .input_handler = semihosting_service_input_handler,
1827 .connection_closed_handler = semihosting_service_connection_closed_handler,
1828 .keep_client_alive_handler = NULL,
1831 /* -------------------------------------------------------------------------
1832 * Common semihosting commands handlers. */
1834 COMMAND_HANDLER(handle_common_semihosting_command)
1836 struct target *target = get_current_target(CMD_CTX);
1838 if (!target) {
1839 LOG_ERROR("No target selected");
1840 return ERROR_FAIL;
1843 struct semihosting *semihosting = target->semihosting;
1844 if (!semihosting) {
1845 command_print(CMD, "semihosting not supported for current target");
1846 return ERROR_FAIL;
1849 if (CMD_ARGC > 0) {
1850 int is_active;
1852 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1854 if (!target_was_examined(target)) {
1855 LOG_ERROR("Target not examined yet");
1856 return ERROR_FAIL;
1859 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1860 LOG_ERROR("Failed to Configure semihosting");
1861 return ERROR_FAIL;
1864 /* FIXME never let that "catch" be dropped! (???) */
1865 semihosting->is_active = is_active;
1868 command_print(CMD, "semihosting is %s",
1869 semihosting->is_active
1870 ? "enabled" : "disabled");
1872 return ERROR_OK;
1875 COMMAND_HANDLER(handle_common_semihosting_redirect_command)
1877 struct target *target = get_current_target(CMD_CTX);
1879 if (!target) {
1880 LOG_ERROR("No target selected");
1881 return ERROR_FAIL;
1884 struct semihosting *semihosting = target->semihosting;
1885 if (!semihosting) {
1886 command_print(CMD, "semihosting not supported for current target");
1887 return ERROR_FAIL;
1890 if (!semihosting->is_active) {
1891 command_print(CMD, "semihosting not yet enabled for current target");
1892 return ERROR_FAIL;
1895 enum semihosting_redirect_config cfg;
1896 const char *port;
1898 if (CMD_ARGC < 1)
1899 return ERROR_COMMAND_SYNTAX_ERROR;
1901 if (strcmp(CMD_ARGV[0], "disable") == 0) {
1902 cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
1903 if (CMD_ARGC > 1)
1904 return ERROR_COMMAND_SYNTAX_ERROR;
1905 } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
1906 if (CMD_ARGC < 2 || CMD_ARGC > 3)
1907 return ERROR_COMMAND_SYNTAX_ERROR;
1909 port = CMD_ARGV[1];
1911 cfg = SEMIHOSTING_REDIRECT_CFG_ALL;
1912 if (CMD_ARGC == 3) {
1913 if (strcmp(CMD_ARGV[2], "debug") == 0)
1914 cfg = SEMIHOSTING_REDIRECT_CFG_DEBUG;
1915 else if (strcmp(CMD_ARGV[2], "stdio") == 0)
1916 cfg = SEMIHOSTING_REDIRECT_CFG_STDIO;
1917 else if (strcmp(CMD_ARGV[2], "all") != 0)
1918 return ERROR_COMMAND_SYNTAX_ERROR;
1920 } else {
1921 return ERROR_COMMAND_SYNTAX_ERROR;
1924 semihosting_tcp_close_cnx(semihosting);
1925 semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
1927 if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) {
1928 struct semihosting_tcp_service *service =
1929 calloc(1, sizeof(struct semihosting_tcp_service));
1930 if (!service) {
1931 LOG_ERROR("Failed to allocate semihosting TCP service.");
1932 return ERROR_FAIL;
1935 service->semihosting = semihosting;
1937 service->name = alloc_printf("%s semihosting service", target_name(target));
1938 if (!service->name) {
1939 LOG_ERROR("Out of memory");
1940 free(service);
1941 return ERROR_FAIL;
1944 int ret = add_service(&semihosting_service_driver,
1945 port, 1, service);
1947 if (ret != ERROR_OK) {
1948 LOG_ERROR("failed to initialize %s", service->name);
1949 free(service->name);
1950 free(service);
1951 return ERROR_FAIL;
1955 semihosting->redirect_cfg = cfg;
1957 return ERROR_OK;
1960 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1962 struct target *target = get_current_target(CMD_CTX);
1964 if (!target) {
1965 LOG_ERROR("No target selected");
1966 return ERROR_FAIL;
1969 struct semihosting *semihosting = target->semihosting;
1970 if (!semihosting) {
1971 command_print(CMD, "semihosting not supported for current target");
1972 return ERROR_FAIL;
1975 if (!semihosting->is_active) {
1976 command_print(CMD, "semihosting not yet enabled for current target");
1977 return ERROR_FAIL;
1980 if (CMD_ARGC > 0)
1981 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1983 command_print(CMD, "semihosting fileio is %s",
1984 semihosting->is_fileio
1985 ? "enabled" : "disabled");
1987 return ERROR_OK;
1990 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1992 struct target *target = get_current_target(CMD_CTX);
1993 unsigned int i;
1995 if (!target) {
1996 LOG_ERROR("No target selected");
1997 return ERROR_FAIL;
2000 struct semihosting *semihosting = target->semihosting;
2001 if (!semihosting) {
2002 command_print(CMD, "semihosting not supported for current target");
2003 return ERROR_FAIL;
2006 free(semihosting->cmdline);
2007 semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
2009 for (i = 1; i < CMD_ARGC; i++) {
2010 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
2011 if (!cmdline)
2012 break;
2013 free(semihosting->cmdline);
2014 semihosting->cmdline = cmdline;
2017 command_print(CMD, "semihosting command line is [%s]",
2018 semihosting->cmdline);
2020 return ERROR_OK;
2023 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
2025 struct target *target = get_current_target(CMD_CTX);
2027 if (!target) {
2028 LOG_ERROR("No target selected");
2029 return ERROR_FAIL;
2032 struct semihosting *semihosting = target->semihosting;
2033 if (!semihosting) {
2034 command_print(CMD, "semihosting not supported for current target");
2035 return ERROR_FAIL;
2038 if (!semihosting->is_active) {
2039 command_print(CMD, "semihosting not yet enabled for current target");
2040 return ERROR_FAIL;
2043 if (CMD_ARGC > 0)
2044 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
2046 command_print(CMD, "semihosting resumable exit is %s",
2047 semihosting->has_resumable_exit
2048 ? "enabled" : "disabled");
2050 return ERROR_OK;
2053 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
2055 struct target *target = get_current_target(CMD_CTX);
2056 struct semihosting *semihosting = target->semihosting;
2058 if (CMD_ARGC)
2059 return ERROR_COMMAND_SYNTAX_ERROR;
2061 if (!semihosting->is_active) {
2062 LOG_ERROR("semihosting not yet enabled for current target");
2063 return ERROR_FAIL;
2066 if (!semihosting_user_op_params) {
2067 LOG_ERROR("This command is usable only from a registered user "
2068 "semihosting event callback.");
2069 return ERROR_FAIL;
2072 command_print_sameline(CMD, "%s", semihosting_user_op_params);
2074 return ERROR_OK;
2077 COMMAND_HANDLER(handle_common_semihosting_basedir_command)
2079 struct target *target = get_current_target(CMD_CTX);
2081 if (CMD_ARGC > 1)
2082 return ERROR_COMMAND_SYNTAX_ERROR;
2084 if (!target) {
2085 LOG_ERROR("No target selected");
2086 return ERROR_FAIL;
2089 struct semihosting *semihosting = target->semihosting;
2090 if (!semihosting) {
2091 command_print(CMD, "semihosting not supported for current target");
2092 return ERROR_FAIL;
2095 if (!semihosting->is_active) {
2096 command_print(CMD, "semihosting not yet enabled for current target");
2097 return ERROR_FAIL;
2100 if (CMD_ARGC > 0) {
2101 free(semihosting->basedir);
2102 semihosting->basedir = strdup(CMD_ARGV[0]);
2103 if (!semihosting->basedir) {
2104 command_print(CMD, "semihosting failed to allocate memory for basedir!");
2105 return ERROR_FAIL;
2109 command_print(CMD, "semihosting base dir: %s",
2110 semihosting->basedir ? semihosting->basedir : "");
2112 return ERROR_OK;
2115 const struct command_registration semihosting_common_handlers[] = {
2117 .name = "semihosting",
2118 .handler = handle_common_semihosting_command,
2119 .mode = COMMAND_EXEC,
2120 .usage = "['enable'|'disable']",
2121 .help = "activate support for semihosting operations",
2124 .name = "semihosting_redirect",
2125 .handler = handle_common_semihosting_redirect_command,
2126 .mode = COMMAND_EXEC,
2127 .usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2128 .help = "redirect semihosting IO",
2131 .name = "semihosting_cmdline",
2132 .handler = handle_common_semihosting_cmdline,
2133 .mode = COMMAND_EXEC,
2134 .usage = "arguments",
2135 .help = "command line arguments to be passed to program",
2138 .name = "semihosting_fileio",
2139 .handler = handle_common_semihosting_fileio_command,
2140 .mode = COMMAND_EXEC,
2141 .usage = "['enable'|'disable']",
2142 .help = "activate support for semihosting fileio operations",
2145 .name = "semihosting_resexit",
2146 .handler = handle_common_semihosting_resumable_exit_command,
2147 .mode = COMMAND_EXEC,
2148 .usage = "['enable'|'disable']",
2149 .help = "activate support for semihosting resumable exit",
2152 .name = "semihosting_read_user_param",
2153 .handler = handle_common_semihosting_read_user_param_command,
2154 .mode = COMMAND_EXEC,
2155 .usage = "",
2156 .help = "read parameters in semihosting-user-cmd-0x10X callbacks",
2159 .name = "semihosting_basedir",
2160 .handler = handle_common_semihosting_basedir_command,
2161 .mode = COMMAND_EXEC,
2162 .usage = "[dir]",
2163 .help = "set the base directory for semihosting I/O operations",
2165 COMMAND_REGISTRATION_DONE