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>
55 static const int open_modeflags[12] = {
60 O_WRONLY | O_CREAT | O_TRUNC,
61 O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
62 O_RDWR | O_CREAT | O_TRUNC,
63 O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
64 O_WRONLY | O_CREAT | O_APPEND,
65 O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
66 O_RDWR | O_CREAT | O_APPEND,
67 O_RDWR | O_CREAT | O_APPEND | O_BINARY
70 static int semihosting_common_fileio_info(struct target *target,
71 struct gdb_fileio_info *fileio_info);
72 static int semihosting_common_fileio_end(struct target *target, int result,
73 int fileio_errno, bool ctrl_c);
75 static int semihosting_read_fields(struct target *target, size_t number,
77 static int semihosting_write_fields(struct target *target, size_t number,
79 static uint64_t semihosting_get_field(struct target *target, size_t index,
81 static void semihosting_set_field(struct target *target, uint64_t value,
85 /* Attempts to include gdb_server.h failed. */
86 extern int gdb_actual_connections;
89 * Initialize common semihosting support.
91 * @param target Pointer to the target to initialize.
94 * @return An error status if there is a problem during initialization.
96 int semihosting_common_init(struct target *target, void *setup,
101 target->fileio_info = malloc(sizeof(*target->fileio_info));
102 if (!target->fileio_info) {
103 LOG_ERROR("out of memory");
106 memset(target->fileio_info, 0, sizeof(*target->fileio_info));
108 struct semihosting *semihosting;
109 semihosting = malloc(sizeof(*target->semihosting));
111 LOG_ERROR("out of memory");
115 semihosting->is_active = false;
116 semihosting->is_fileio = false;
117 semihosting->hit_fileio = false;
118 semihosting->is_resumable = false;
119 semihosting->has_resumable_exit = false;
120 semihosting->word_size_bytes = 0;
121 semihosting->op = -1;
122 semihosting->param = 0;
123 semihosting->result = -1;
124 semihosting->sys_errno = -1;
125 semihosting->cmdline = NULL;
127 /* If possible, update it in setup(). */
128 semihosting->setup_time = clock();
130 semihosting->setup = setup;
131 semihosting->post_result = post_result;
133 target->semihosting = semihosting;
135 target->type->get_gdb_fileio_info = semihosting_common_fileio_info;
136 target->type->gdb_fileio_end = semihosting_common_fileio_end;
142 * Portable implementation of ARM semihosting calls.
143 * Performs the currently pending semihosting operation
144 * encoded in target->semihosting.
146 int semihosting_common(struct target *target)
148 struct semihosting *semihosting = target->semihosting;
150 /* Silently ignore if the semihosting field was not set. */
154 struct gdb_fileio_info *fileio_info = target->fileio_info;
157 * By default return an error.
158 * The actual result must be set by each function
160 semihosting->result = -1;
162 /* Most operations are resumable, except the two exit calls. */
163 semihosting->is_resumable = true;
167 /* Enough space to hold 4 long words. */
170 LOG_DEBUG("op=0x%x, param=0x%" PRIx64, (int)semihosting->op,
173 switch (semihosting->op) {
175 case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
177 * Returns the number of centiseconds (hundredths of a second)
178 * since the execution started.
180 * Values returned can be of limited use for some benchmarking
181 * purposes because of communication overhead or other
182 * agent-specific factors. For example, with a debug hardware
183 * unit the request is passed back to the host for execution.
184 * This can lead to unpredictable delays in transmission and
185 * process scheduling.
187 * Use this function to calculate time intervals, by calculating
188 * differences between intervals with and without the code
189 * sequence to be timed.
192 * The PARAMETER REGISTER must contain 0. There are no other
196 * On exit, the RETURN REGISTER contains:
197 * - The number of centiseconds since some arbitrary start
198 * point, if the call is successful.
199 * - –1 if the call is not successful. For example, because
200 * of a communications error.
203 clock_t delta = clock() - semihosting->setup_time;
205 semihosting->result = delta / (CLOCKS_PER_SEC / 100);
209 case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
211 * Closes a file on the host system. The handle must reference
212 * a file that was opened with SYS_OPEN.
215 * On entry, the PARAMETER REGISTER contains a pointer to a
216 * one-field argument block:
217 * - field 1 Contains a handle for an open file.
220 * On exit, the RETURN REGISTER contains:
221 * - 0 if the call is successful
222 * - –1 if the call is not successful.
224 retval = semihosting_read_fields(target, 1, fields);
225 if (retval != ERROR_OK)
228 int fd = semihosting_get_field(target, 0, fields);
229 /* Do not allow to close OpenOCD's own standard streams */
230 if (fd == 0 || fd == 1 || fd == 2) {
231 LOG_DEBUG("ignoring semihosting attempt to close %s",
232 (fd == 0) ? "stdin" :
233 (fd == 1) ? "stdout" : "stderr");
234 /* Just pretend success */
235 if (semihosting->is_fileio) {
236 semihosting->result = 0;
238 semihosting->result = 0;
239 semihosting->sys_errno = 0;
243 /* Close the descriptor */
244 if (semihosting->is_fileio) {
245 semihosting->hit_fileio = true;
246 fileio_info->identifier = "close";
247 fileio_info->param_1 = fd;
249 semihosting->result = close(fd);
250 semihosting->sys_errno = errno;
251 LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result);
256 case SEMIHOSTING_SYS_ERRNO: /* 0x13 */
258 * Returns the value of the C library errno variable that is
259 * associated with the semihosting implementation. The errno
260 * variable can be set by a number of C library semihosted
261 * functions, including:
269 * Whether errno is set or not, and to what value, is entirely
270 * host-specific, except where the ISO C standard defines the
274 * There are no parameters. The PARAMETER REGISTER must be 0.
277 * On exit, the RETURN REGISTER contains the value of the C
278 * library errno variable.
280 semihosting->result = semihosting->sys_errno;
283 case SEMIHOSTING_SYS_EXIT: /* 0x18 */
285 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
286 * previous versions of the documentation.
288 * An application calls this operation to report an exception
289 * to the debugger directly. The most common use is to report
290 * that execution has completed, using ADP_Stopped_ApplicationExit.
292 * Note: This semihosting operation provides no means for 32-bit
293 * callers to indicate an application exit with a specified exit
294 * code. Semihosting callers may prefer to check for the presence
295 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
296 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
300 * On entry, the PARAMETER register is set to a reason code
301 * describing the cause of the trap. Not all semihosting client
302 * implementations will necessarily trap every corresponding
303 * event. Important reason codes are:
305 * - ADP_Stopped_ApplicationExit 0x20026
306 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
309 * On entry, the PARAMETER REGISTER contains a pointer to a
310 * two-field argument block:
311 * - field 1 The exception type, which is one of the set of
312 * reason codes in the above tables.
313 * - field 2 A subcode, whose meaning depends on the reason
315 * In particular, if field 1 is ADP_Stopped_ApplicationExit
316 * then field 2 is an exit status code, as passed to the C
317 * standard library exit() function. A simulator receiving
318 * this request must notify a connected debugger, if present,
319 * and then exit with the specified status.
322 * No return is expected from these calls. However, it is
323 * possible for the debugger to request that the application
324 * continues by performing an RDI_Execute request or equivalent.
325 * In this case, execution continues with the registers as they
326 * were on entry to the operation, or as subsequently modified
329 if (semihosting->word_size_bytes == 8) {
330 retval = semihosting_read_fields(target, 2, fields);
331 if (retval != ERROR_OK)
334 int type = semihosting_get_field(target, 0, fields);
335 int code = semihosting_get_field(target, 1, fields);
337 if (type == ADP_STOPPED_APPLICATION_EXIT) {
338 if (!gdb_actual_connections)
342 "semihosting: *** application exited with %d ***\n",
347 "semihosting: application exception %#x\n",
352 if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
353 if (!gdb_actual_connections)
357 "semihosting: *** application exited normally ***\n");
359 } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
360 /* Chosen more or less arbitrarily to have a nicer message,
361 * otherwise all other return the same exit code 1. */
362 if (!gdb_actual_connections)
366 "semihosting: *** application exited with error ***\n");
369 if (!gdb_actual_connections)
373 "semihosting: application exception %#x\n",
374 (unsigned) semihosting->param);
378 if (!semihosting->has_resumable_exit) {
379 semihosting->is_resumable = false;
380 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
384 case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
386 * This operation is only supported if the semihosting extension
387 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
388 * reported using feature byte 0, bit 0. If this extension is
389 * supported, then the implementation provides a means to
390 * report a normal exit with a nonzero exit status in both 32-bit
391 * and 64-bit semihosting APIs.
393 * The implementation must provide the semihosting call
394 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
396 * SYS_EXIT_EXTENDED is used by an application to report an
397 * exception or exit to the debugger directly. The most common
398 * use is to report that execution has completed, using
399 * ADP_Stopped_ApplicationExit.
402 * On entry, the PARAMETER REGISTER contains a pointer to a
403 * two-field argument block:
404 * - field 1 The exception type, which should be one of the set
405 * of reason codes that are documented for the SYS_EXIT
406 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
407 * - field 2 A subcode, whose meaning depends on the reason
408 * code in field 1. In particular, if field 1 is
409 * ADP_Stopped_ApplicationExit then field 2 is an exit status
410 * code, as passed to the C standard library exit() function.
411 * A simulator receiving this request must notify a connected
412 * debugger, if present, and then exit with the specified status.
415 * No return is expected from these calls.
417 * For the A64 API, this call is identical to the behavior of
418 * the mandatory SYS_EXIT (0x18) call. If this extension is
419 * supported, then both calls must be implemented.
421 retval = semihosting_read_fields(target, 2, fields);
422 if (retval != ERROR_OK)
425 int type = semihosting_get_field(target, 0, fields);
426 int code = semihosting_get_field(target, 1, fields);
428 if (type == ADP_STOPPED_APPLICATION_EXIT) {
429 if (!gdb_actual_connections)
433 "semihosting: *** application exited with %d ***\n",
437 fprintf(stderr, "semihosting: exception %#x\n",
441 if (!semihosting->has_resumable_exit) {
442 semihosting->is_resumable = false;
443 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
447 case SEMIHOSTING_SYS_FLEN: /* 0x0C */
449 * Returns the length of a specified file.
452 * On entry, the PARAMETER REGISTER contains a pointer to a
453 * one-field argument block:
454 * - field 1 A handle for a previously opened, seekable file
458 * On exit, the RETURN REGISTER contains:
459 * - The current length of the file object, if the call is
461 * - –1 if an error occurs.
463 if (semihosting->is_fileio) {
464 semihosting->result = -1;
465 semihosting->sys_errno = EINVAL;
467 retval = semihosting_read_fields(target, 1, fields);
468 if (retval != ERROR_OK)
471 int fd = semihosting_get_field(target, 0, fields);
473 semihosting->result = fstat(fd, &buf);
474 if (semihosting->result == -1) {
475 semihosting->sys_errno = errno;
476 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
479 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
480 semihosting->result = buf.st_size;
484 case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
486 * Returns the command line that is used for the call to the
487 * executable, that is, argc and argv.
490 * On entry, the PARAMETER REGISTER points to a two-field data
491 * block to be used for returning the command string and its length:
492 * - field 1 A pointer to a buffer of at least the size that is
493 * specified in field 2.
494 * - field 2 The length of the buffer in bytes.
498 * If the call is successful, then the RETURN REGISTER contains 0,
499 * the PARAMETER REGISTER is unchanged, and the data block is
500 * updated as follows:
501 * - field 1 A pointer to a null-terminated string of the command
503 * - field 2 The length of the string in bytes.
504 * If the call is not successful, then the RETURN REGISTER
507 * Note: The semihosting implementation might impose limits on
508 * the maximum length of the string that can be transferred.
509 * However, the implementation must be able to support a
510 * command-line length of at least 80 bytes.
512 retval = semihosting_read_fields(target, 2, fields);
513 if (retval != ERROR_OK)
516 uint64_t addr = semihosting_get_field(target, 0, fields);
517 size_t size = semihosting_get_field(target, 1, fields);
519 char *arg = semihosting->cmdline ?
520 semihosting->cmdline : "";
521 uint32_t len = strlen(arg) + 1;
523 semihosting->result = -1;
525 semihosting_set_field(target, len, 1, fields);
526 retval = target_write_buffer(target, addr, len,
528 if (retval != ERROR_OK)
530 semihosting->result = 0;
532 retval = semihosting_write_fields(target, 2, fields);
533 if (retval != ERROR_OK)
536 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg,
537 (int)semihosting->result);
541 case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
543 * Returns the system stack and heap parameters.
546 * On entry, the PARAMETER REGISTER contains the address of a
547 * pointer to a four-field data block. The contents of the data
548 * block are filled by the function. The following C-like
549 * pseudocode describes the layout of the block:
558 * On exit, the PARAMETER REGISTER is unchanged and the data
559 * block has been updated.
561 retval = semihosting_read_fields(target, 1, fields);
562 if (retval != ERROR_OK)
565 uint64_t addr = semihosting_get_field(target, 0, fields);
566 /* tell the remote we have no idea */
567 memset(fields, 0, 4 * semihosting->word_size_bytes);
568 retval = target_write_memory(target, addr, 4,
569 semihosting->word_size_bytes,
571 if (retval != ERROR_OK)
573 semihosting->result = 0;
577 case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
579 * Determines whether the return code from another semihosting
580 * call is an error status or not.
582 * This call is passed a parameter block containing the error
586 * On entry, the PARAMETER REGISTER contains a pointer to a
587 * one-field data block:
588 * - field 1 The required status word to check.
591 * On exit, the RETURN REGISTER contains:
592 * - 0 if the status field is not an error indication
593 * - A nonzero value if the status field is an error indication.
595 retval = semihosting_read_fields(target, 1, fields);
596 if (retval != ERROR_OK)
599 uint64_t code = semihosting_get_field(target, 0, fields);
600 semihosting->result = (code != 0);
603 case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
605 * Checks whether a file is connected to an interactive device.
608 * On entry, the PARAMETER REGISTER contains a pointer to a
609 * one-field argument block:
610 * field 1 A handle for a previously opened file object.
613 * On exit, the RETURN REGISTER contains:
614 * - 1 if the handle identifies an interactive device.
615 * - 0 if the handle identifies a file.
616 * - A value other than 1 or 0 if an error occurs.
618 if (semihosting->is_fileio) {
619 semihosting->hit_fileio = true;
620 fileio_info->identifier = "isatty";
621 fileio_info->param_1 = semihosting->param;
623 retval = semihosting_read_fields(target, 1, fields);
624 if (retval != ERROR_OK)
626 int fd = semihosting_get_field(target, 0, fields);
627 semihosting->result = isatty(fd);
628 semihosting->sys_errno = errno;
629 LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result);
633 case SEMIHOSTING_SYS_OPEN: /* 0x01 */
635 * Opens a file on the host system.
637 * The file path is specified either as relative to the current
638 * directory of the host process, or absolute, using the path
639 * conventions of the host operating system.
641 * Semihosting implementations must support opening the special
642 * path name :semihosting-features as part of the semihosting
643 * extensions reporting mechanism.
645 * ARM targets interpret the special path name :tt as meaning
646 * the console input stream, for an open-read or the console
647 * output stream, for an open-write. Opening these streams is
648 * performed as part of the standard startup code for those
649 * applications that reference the C stdio streams. The
650 * semihosting extension SH_EXT_STDOUT_STDERR allows the
651 * semihosting caller to open separate output streams
652 * corresponding to stdout and stderr. This extension is
653 * reported using feature byte 0, bit 1. Use SYS_OPEN with
654 * the special path name :semihosting-features to access the
657 * If this extension is supported, the implementation must
658 * support the following additional semantics to SYS_OPEN:
659 * - If the special path name :tt is opened with an fopen
660 * mode requesting write access (w, wb, w+, or w+b), then
661 * this is a request to open stdout.
662 * - If the special path name :tt is opened with a mode
663 * requesting append access (a, ab, a+, or a+b), then this is
664 * a request to open stderr.
667 * On entry, the PARAMETER REGISTER contains a pointer to a
668 * three-field argument block:
669 * - field 1 A pointer to a null-terminated string containing
670 * a file or device name.
671 * - field 2 An integer that specifies the file opening mode.
672 * - field 3 An integer that gives the length of the string
673 * pointed to by field 1.
675 * The length does not include the terminating null character
676 * that must be present.
679 * On exit, the RETURN REGISTER contains:
680 * - A nonzero handle if the call is successful.
681 * - –1 if the call is not successful.
683 retval = semihosting_read_fields(target, 3, fields);
684 if (retval != ERROR_OK)
687 uint64_t addr = semihosting_get_field(target, 0, fields);
688 uint32_t mode = semihosting_get_field(target, 1, fields);
689 size_t len = semihosting_get_field(target, 2, fields);
692 semihosting->result = -1;
693 semihosting->sys_errno = EINVAL;
696 uint8_t *fn = malloc(len+1);
698 semihosting->result = -1;
699 semihosting->sys_errno = ENOMEM;
701 retval = target_read_memory(target, addr, 1, len, fn);
702 if (retval != ERROR_OK) {
707 /* TODO: implement the :semihosting-features special file.
709 if (semihosting->is_fileio) {
710 if (strcmp((char *)fn, ":semihosting-features") == 0) {
711 semihosting->result = -1;
712 semihosting->sys_errno = EINVAL;
713 } else if (strcmp((char *)fn, ":tt") == 0) {
715 semihosting->result = 0;
717 semihosting->result = 1;
719 semihosting->result = 2;
721 semihosting->result = -1;
723 semihosting->hit_fileio = true;
724 fileio_info->identifier = "open";
725 fileio_info->param_1 = addr;
726 fileio_info->param_2 = len;
727 fileio_info->param_3 = open_modeflags[mode];
728 fileio_info->param_4 = 0644;
731 if (strcmp((char *)fn, ":tt") == 0) {
733 * - 0-3 ("r") for stdin,
734 * - 4-7 ("w") for stdout,
735 * - 8-11 ("a") for stderr */
737 semihosting->result = dup(
739 semihosting->sys_errno = errno;
740 LOG_DEBUG("dup(STDIN)=%d",
741 (int)semihosting->result);
742 } else if (mode < 8) {
743 semihosting->result = dup(
745 semihosting->sys_errno = errno;
746 LOG_DEBUG("dup(STDOUT)=%d",
747 (int)semihosting->result);
749 semihosting->result = dup(
751 semihosting->sys_errno = errno;
752 LOG_DEBUG("dup(STDERR)=%d",
753 (int)semihosting->result);
756 /* cygwin requires the permission setting
757 * otherwise it will fail to reopen a previously
759 semihosting->result = open((char *)fn,
760 open_modeflags[mode],
762 semihosting->sys_errno = errno;
763 LOG_DEBUG("open('%s')=%d", fn,
764 (int)semihosting->result);
772 case SEMIHOSTING_SYS_READ: /* 0x06 */
774 * Reads the contents of a file into a buffer. The file position
775 * is specified either:
776 * - Explicitly by a SYS_SEEK.
777 * - Implicitly one byte beyond the previous SYS_READ or
780 * The file position is at the start of the file when it is
781 * opened, and is lost when the file is closed. Perform the
782 * file operation as a single action whenever possible. For
783 * example, do not split a read of 16KB into four 4KB chunks
784 * unless there is no alternative.
787 * On entry, the PARAMETER REGISTER contains a pointer to a
788 * three-field data block:
789 * - field 1 Contains a handle for a file previously opened
791 * - field 2 Points to a buffer.
792 * - field 3 Contains the number of bytes to read to the buffer
796 * On exit, the RETURN REGISTER contains the number of bytes not
797 * filled in the buffer (buffer_length - bytes_read) as follows:
798 * - If the RETURN REGISTER is 0, the entire buffer was
799 * successfully filled.
800 * - If the RETURN REGISTER is the same as field 3, no bytes
801 * were read (EOF can be assumed).
802 * - If the RETURN REGISTER contains a value smaller than
803 * field 3, the read succeeded but the buffer was only partly
804 * filled. For interactive devices, this is the most common
807 retval = semihosting_read_fields(target, 3, fields);
808 if (retval != ERROR_OK)
811 int fd = semihosting_get_field(target, 0, fields);
812 uint64_t addr = semihosting_get_field(target, 1, fields);
813 size_t len = semihosting_get_field(target, 2, fields);
814 if (semihosting->is_fileio) {
815 semihosting->hit_fileio = true;
816 fileio_info->identifier = "read";
817 fileio_info->param_1 = fd;
818 fileio_info->param_2 = addr;
819 fileio_info->param_3 = len;
821 uint8_t *buf = malloc(len);
823 semihosting->result = -1;
824 semihosting->sys_errno = ENOMEM;
826 semihosting->result = read(fd, buf, len);
827 semihosting->sys_errno = errno;
828 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
832 (int)semihosting->result);
833 if (semihosting->result >= 0) {
834 retval = target_write_buffer(target, addr,
837 if (retval != ERROR_OK) {
841 /* the number of bytes NOT filled in */
842 semihosting->result = len -
851 case SEMIHOSTING_SYS_READC: /* 0x07 */
853 * Reads a byte from the console.
856 * The PARAMETER REGISTER must contain 0. There are no other
857 * parameters or values possible.
860 * On exit, the RETURN REGISTER contains the byte read from
863 if (semihosting->is_fileio) {
864 LOG_ERROR("SYS_READC not supported by semihosting fileio");
867 semihosting->result = getchar();
868 LOG_DEBUG("getchar()=%d", (int)semihosting->result);
871 case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
873 * Deletes a specified file on the host filing system.
876 * On entry, the PARAMETER REGISTER contains a pointer to a
877 * two-field argument block:
878 * - field 1 Points to a null-terminated string that gives the
879 * path name of the file to be deleted.
880 * - field 2 The length of the string.
883 * On exit, the RETURN REGISTER contains:
884 * - 0 if the delete is successful
885 * - A nonzero, host-specific error code if the delete fails.
887 retval = semihosting_read_fields(target, 2, fields);
888 if (retval != ERROR_OK)
891 uint64_t addr = semihosting_get_field(target, 0, fields);
892 size_t len = semihosting_get_field(target, 1, fields);
893 if (semihosting->is_fileio) {
894 semihosting->hit_fileio = true;
895 fileio_info->identifier = "unlink";
896 fileio_info->param_1 = addr;
897 fileio_info->param_2 = len;
899 uint8_t *fn = malloc(len+1);
901 semihosting->result = -1;
902 semihosting->sys_errno = ENOMEM;
905 target_read_memory(target, addr, 1, len,
907 if (retval != ERROR_OK) {
912 semihosting->result = remove((char *)fn);
913 semihosting->sys_errno = errno;
914 LOG_DEBUG("remove('%s')=%d", fn,
915 (int)semihosting->result);
923 case SEMIHOSTING_SYS_RENAME: /* 0x0F */
925 * Renames a specified file.
928 * On entry, the PARAMETER REGISTER contains a pointer to a
929 * four-field data block:
930 * - field 1 A pointer to the name of the old file.
931 * - field 2 The length of the old filename.
932 * - field 3 A pointer to the new filename.
933 * - field 4 The length of the new filename. Both strings are
937 * On exit, the RETURN REGISTER contains:
938 * - 0 if the rename is successful.
939 * - A nonzero, host-specific error code if the rename fails.
941 retval = semihosting_read_fields(target, 4, fields);
942 if (retval != ERROR_OK)
945 uint64_t addr1 = semihosting_get_field(target, 0, fields);
946 size_t len1 = semihosting_get_field(target, 1, fields);
947 uint64_t addr2 = semihosting_get_field(target, 2, fields);
948 size_t len2 = semihosting_get_field(target, 3, fields);
949 if (semihosting->is_fileio) {
950 semihosting->hit_fileio = true;
951 fileio_info->identifier = "rename";
952 fileio_info->param_1 = addr1;
953 fileio_info->param_2 = len1;
954 fileio_info->param_3 = addr2;
955 fileio_info->param_4 = len2;
957 uint8_t *fn1 = malloc(len1+1);
958 uint8_t *fn2 = malloc(len2+1);
962 semihosting->result = -1;
963 semihosting->sys_errno = ENOMEM;
965 retval = target_read_memory(target, addr1, 1, len1,
967 if (retval != ERROR_OK) {
972 retval = target_read_memory(target, addr2, 1, len2,
974 if (retval != ERROR_OK) {
981 semihosting->result = rename((char *)fn1,
983 semihosting->sys_errno = errno;
984 LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2,
985 (int)semihosting->result);
994 case SEMIHOSTING_SYS_SEEK: /* 0x0A */
996 * Seeks to a specified position in a file using an offset
997 * specified from the start of the file. The file is assumed
998 * to be a byte array and the offset is given in bytes.
1001 * On entry, the PARAMETER REGISTER contains a pointer to a
1002 * two-field data block:
1003 * - field 1 A handle for a seekable file object.
1004 * - field 2 The absolute byte position to seek to.
1007 * On exit, the RETURN REGISTER contains:
1008 * - 0 if the request is successful.
1009 * - A negative value if the request is not successful.
1010 * Use SYS_ERRNO to read the value of the host errno variable
1011 * describing the error.
1013 * Note: The effect of seeking outside the current extent of
1014 * the file object is undefined.
1016 retval = semihosting_read_fields(target, 2, fields);
1017 if (retval != ERROR_OK)
1020 int fd = semihosting_get_field(target, 0, fields);
1021 off_t pos = semihosting_get_field(target, 1, fields);
1022 if (semihosting->is_fileio) {
1023 semihosting->hit_fileio = true;
1024 fileio_info->identifier = "lseek";
1025 fileio_info->param_1 = fd;
1026 fileio_info->param_2 = pos;
1027 fileio_info->param_3 = SEEK_SET;
1029 semihosting->result = lseek(fd, pos, SEEK_SET);
1030 semihosting->sys_errno = errno;
1031 LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos,
1032 (int)semihosting->result);
1033 if (semihosting->result == pos)
1034 semihosting->result = 0;
1039 case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1041 * Passes a command to the host command-line interpreter.
1042 * This enables you to execute a system command such as dir,
1043 * ls, or pwd. The terminal I/O is on the host, and is not
1044 * visible to the target.
1047 * On entry, the PARAMETER REGISTER contains a pointer to a
1048 * two-field argument block:
1049 * - field 1 Points to a string to be passed to the host
1050 * command-line interpreter.
1051 * - field 2 The length of the string.
1054 * On exit, the RETURN REGISTER contains the return status.
1057 /* Provide SYS_SYSTEM functionality. Uses the
1058 * libc system command, there may be a reason *NOT*
1059 * to use this, but as I can't think of one, I
1060 * implemented it this way.
1062 retval = semihosting_read_fields(target, 2, fields);
1063 if (retval != ERROR_OK)
1066 uint64_t addr = semihosting_get_field(target, 0, fields);
1067 size_t len = semihosting_get_field(target, 1, fields);
1068 if (semihosting->is_fileio) {
1069 semihosting->hit_fileio = true;
1070 fileio_info->identifier = "system";
1071 fileio_info->param_1 = addr;
1072 fileio_info->param_2 = len;
1074 uint8_t *cmd = malloc(len+1);
1076 semihosting->result = -1;
1077 semihosting->sys_errno = ENOMEM;
1079 retval = target_read_memory(target,
1084 if (retval != ERROR_OK) {
1089 semihosting->result = system(
1091 LOG_DEBUG("system('%s')=%d",
1093 (int)semihosting->result);
1102 case SEMIHOSTING_SYS_TIME: /* 0x11 */
1104 * Returns the number of seconds since 00:00 January 1, 1970.
1105 * This value is real-world time, regardless of any debug agent
1109 * There are no parameters.
1112 * On exit, the RETURN REGISTER contains the number of seconds.
1114 semihosting->result = time(NULL);
1117 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1119 * Writes the contents of a buffer to a specified file at the
1120 * current file position. The file position is specified either:
1121 * - Explicitly, by a SYS_SEEK.
1122 * - Implicitly as one byte beyond the previous SYS_READ or
1123 * SYS_WRITE request.
1125 * The file position is at the start of the file when the file
1126 * is opened, and is lost when the file is closed.
1128 * Perform the file operation as a single action whenever
1129 * possible. For example, do not split a write of 16KB into
1130 * four 4KB chunks unless there is no alternative.
1133 * On entry, the PARAMETER REGISTER contains a pointer to a
1134 * three-field data block:
1135 * - field 1 Contains a handle for a file previously opened
1137 * - field 2 Points to the memory containing the data to be written.
1138 * - field 3 Contains the number of bytes to be written from
1139 * the buffer to the file.
1142 * On exit, the RETURN REGISTER contains:
1143 * - 0 if the call is successful.
1144 * - The number of bytes that are not written, if there is an error.
1146 retval = semihosting_read_fields(target, 3, fields);
1147 if (retval != ERROR_OK)
1150 int fd = semihosting_get_field(target, 0, fields);
1151 uint64_t addr = semihosting_get_field(target, 1, fields);
1152 size_t len = semihosting_get_field(target, 2, fields);
1153 if (semihosting->is_fileio) {
1154 semihosting->hit_fileio = true;
1155 fileio_info->identifier = "write";
1156 fileio_info->param_1 = fd;
1157 fileio_info->param_2 = addr;
1158 fileio_info->param_3 = len;
1160 uint8_t *buf = malloc(len);
1162 semihosting->result = -1;
1163 semihosting->sys_errno = ENOMEM;
1165 retval = target_read_buffer(target, addr, len, buf);
1166 if (retval != ERROR_OK) {
1170 semihosting->result = write(fd, buf, len);
1171 semihosting->sys_errno = errno;
1172 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
1176 (int)semihosting->result);
1177 if (semihosting->result >= 0) {
1178 /* The number of bytes that are NOT written.
1180 semihosting->result = len -
1181 semihosting->result;
1190 case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1192 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1193 * to the debug channel. When executed under a semihosting
1194 * debugger, the character appears on the host debugger console.
1197 * On entry, the PARAMETER REGISTER contains a pointer to the
1201 * None. The RETURN REGISTER is corrupted.
1203 if (semihosting->is_fileio) {
1204 semihosting->hit_fileio = true;
1205 fileio_info->identifier = "write";
1206 fileio_info->param_1 = 1;
1207 fileio_info->param_2 = semihosting->param;
1208 fileio_info->param_3 = 1;
1210 uint64_t addr = semihosting->param;
1212 retval = target_read_memory(target, addr, 1, 1, &c);
1213 if (retval != ERROR_OK)
1216 semihosting->result = 0;
1220 case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1222 * Writes a null-terminated string to the debug channel.
1223 * When executed under a semihosting debugger, the characters
1224 * appear on the host debugger console.
1227 * On entry, the PARAMETER REGISTER contains a pointer to the
1228 * first byte of the string.
1231 * None. The RETURN REGISTER is corrupted.
1233 if (semihosting->is_fileio) {
1235 uint64_t addr = semihosting->param;
1238 retval = target_read_memory(target, addr, 1, 1, &c);
1239 if (retval != ERROR_OK)
1245 semihosting->hit_fileio = true;
1246 fileio_info->identifier = "write";
1247 fileio_info->param_1 = 1;
1248 fileio_info->param_2 = semihosting->param;
1249 fileio_info->param_3 = count;
1251 uint64_t addr = semihosting->param;
1254 retval = target_read_memory(target, addr++, 1, 1, &c);
1255 if (retval != ERROR_OK)
1261 semihosting->result = 0;
1265 case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1267 * Returns the number of elapsed target ticks since execution
1269 * Use SYS_TICKFREQ to determine the tick frequency.
1272 * On entry, the PARAMETER REGISTER points to a two-field data
1273 * block to be used for returning the number of elapsed ticks:
1274 * - field 1 The least significant field and is at the low address.
1275 * - field 2 The most significant field and is at the high address.
1278 * On entry the PARAMETER REGISTER points to a one-field data
1279 * block to be used for returning the number of elapsed ticks:
1280 * - field 1 The number of elapsed ticks as a 64-bit value.
1284 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1285 * REGISTER is unchanged, and the data block pointed to by the
1286 * PARAMETER REGISTER is filled in with the number of elapsed
1288 * - On failure, the RETURN REGISTER contains -1, and the
1289 * PARAMETER REGISTER contains -1.
1291 * Note: Some semihosting implementations might not support this
1292 * semihosting operation, and they always return -1 in the
1296 case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1298 * Returns the tick frequency.
1301 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1304 * On exit, the RETURN REGISTER contains either:
1305 * - The number of ticks per second.
1306 * - –1 if the target does not know the value of one tick.
1308 * Note: Some semihosting implementations might not support
1309 * this semihosting operation, and they always return -1 in the
1313 case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1315 * Returns a temporary name for a file identified by a system
1319 * On entry, the PARAMETER REGISTER contains a pointer to a
1320 * three-word argument block:
1321 * - field 1 A pointer to a buffer.
1322 * - field 2 A target identifier for this filename. Its value
1323 * must be an integer in the range 0-255.
1324 * - field 3 Contains the length of the buffer. The length must
1325 * be at least the value of L_tmpnam on the host system.
1328 * On exit, the RETURN REGISTER contains:
1329 * - 0 if the call is successful.
1330 * - –1 if an error occurs.
1332 * The buffer pointed to by the PARAMETER REGISTER contains
1333 * the filename, prefixed with a suitable directory name.
1334 * If you use the same target identifier again, the same
1335 * filename is returned.
1337 * Note: The returned string must be null-terminated.
1341 fprintf(stderr, "semihosting: unsupported call %#x\n",
1342 (unsigned) semihosting->op);
1343 semihosting->result = -1;
1344 semihosting->sys_errno = ENOTSUP;
1347 if (!semihosting->hit_fileio) {
1348 retval = semihosting->post_result(target);
1349 if (retval != ERROR_OK) {
1350 LOG_ERROR("Failed to post semihosting result");
1358 /* -------------------------------------------------------------------------
1359 * Local functions. */
1361 static int semihosting_common_fileio_info(struct target *target,
1362 struct gdb_fileio_info *fileio_info)
1364 struct semihosting *semihosting = target->semihosting;
1369 * To avoid unnecessary duplication, semihosting prepares the
1370 * fileio_info structure out-of-band when the target halts. See
1371 * do_semihosting for more detail.
1373 if (!semihosting->is_fileio || !semihosting->hit_fileio)
1379 static int semihosting_common_fileio_end(struct target *target, int result,
1380 int fileio_errno, bool ctrl_c)
1382 struct gdb_fileio_info *fileio_info = target->fileio_info;
1383 struct semihosting *semihosting = target->semihosting;
1387 /* clear pending status */
1388 semihosting->hit_fileio = false;
1390 semihosting->result = result;
1391 semihosting->sys_errno = fileio_errno;
1394 * Some fileio results do not match up with what the semihosting
1395 * operation expects; for these operations, we munge the results
1398 switch (semihosting->op) {
1399 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1401 semihosting->result = fileio_info->param_3;
1403 semihosting->result = 0;
1406 case SEMIHOSTING_SYS_READ: /* 0x06 */
1407 if (result == (int)fileio_info->param_3)
1408 semihosting->result = 0;
1410 semihosting->result = fileio_info->param_3;
1413 case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1415 semihosting->result = 0;
1419 return semihosting->post_result(target);
1423 * Read all fields of a command from target to buffer.
1425 static int semihosting_read_fields(struct target *target, size_t number,
1428 struct semihosting *semihosting = target->semihosting;
1429 /* Use 4-byte multiples to trigger fast memory access. */
1430 return target_read_memory(target, semihosting->param, 4,
1431 number * (semihosting->word_size_bytes / 4), fields);
1435 * Write all fields of a command from buffer to target.
1437 static int semihosting_write_fields(struct target *target, size_t number,
1440 struct semihosting *semihosting = target->semihosting;
1441 /* Use 4-byte multiples to trigger fast memory access. */
1442 return target_write_memory(target, semihosting->param, 4,
1443 number * (semihosting->word_size_bytes / 4), fields);
1447 * Extract a field from the buffer, considering register size and endianness.
1449 static uint64_t semihosting_get_field(struct target *target, size_t index,
1452 struct semihosting *semihosting = target->semihosting;
1453 if (semihosting->word_size_bytes == 8)
1454 return target_buffer_get_u64(target, fields + (index * 8));
1456 return target_buffer_get_u32(target, fields + (index * 4));
1460 * Store a field in the buffer, considering register size and endianness.
1462 static void semihosting_set_field(struct target *target, uint64_t value,
1466 struct semihosting *semihosting = target->semihosting;
1467 if (semihosting->word_size_bytes == 8)
1468 target_buffer_set_u64(target, fields + (index * 8), value);
1470 target_buffer_set_u32(target, fields + (index * 4), value);
1474 /* -------------------------------------------------------------------------
1475 * Common semihosting commands handlers. */
1477 COMMAND_HANDLER(handle_common_semihosting_command)
1479 struct target *target = get_current_target(CMD_CTX);
1482 LOG_ERROR("No target selected");
1486 struct semihosting *semihosting = target->semihosting;
1488 command_print(CMD, "semihosting not supported for current target");
1495 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1497 if (!target_was_examined(target)) {
1498 LOG_ERROR("Target not examined yet");
1502 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1503 LOG_ERROR("Failed to Configure semihosting");
1507 /* FIXME never let that "catch" be dropped! (???) */
1508 semihosting->is_active = is_active;
1511 command_print(CMD, "semihosting is %s",
1512 semihosting->is_active
1513 ? "enabled" : "disabled");
1518 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1520 struct target *target = get_current_target(CMD_CTX);
1523 LOG_ERROR("No target selected");
1527 struct semihosting *semihosting = target->semihosting;
1529 command_print(CMD, "semihosting not supported for current target");
1533 if (!semihosting->is_active) {
1534 command_print(CMD, "semihosting not yet enabled for current target");
1539 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1541 command_print(CMD, "semihosting fileio is %s",
1542 semihosting->is_fileio
1543 ? "enabled" : "disabled");
1548 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1550 struct target *target = get_current_target(CMD_CTX);
1554 LOG_ERROR("No target selected");
1558 struct semihosting *semihosting = target->semihosting;
1560 command_print(CMD, "semihosting not supported for current target");
1564 free(semihosting->cmdline);
1565 semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
1567 for (i = 1; i < CMD_ARGC; i++) {
1568 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
1571 free(semihosting->cmdline);
1572 semihosting->cmdline = cmdline;
1575 command_print(CMD, "semihosting command line is [%s]",
1576 semihosting->cmdline);
1581 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
1583 struct target *target = get_current_target(CMD_CTX);
1586 LOG_ERROR("No target selected");
1590 struct semihosting *semihosting = target->semihosting;
1592 command_print(CMD, "semihosting not supported for current target");
1596 if (!semihosting->is_active) {
1597 command_print(CMD, "semihosting not yet enabled for current target");
1602 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
1604 command_print(CMD, "semihosting resumable exit is %s",
1605 semihosting->has_resumable_exit
1606 ? "enabled" : "disabled");
1611 const struct command_registration semihosting_common_handlers[] = {
1614 .handler = handle_common_semihosting_command,
1615 .mode = COMMAND_EXEC,
1616 .usage = "['enable'|'disable']",
1617 .help = "activate support for semihosting operations",
1620 "semihosting_cmdline",
1621 .handler = handle_common_semihosting_cmdline,
1622 .mode = COMMAND_EXEC,
1623 .usage = "arguments",
1624 .help = "command line arguments to be passed to program",
1627 "semihosting_fileio",
1628 .handler = handle_common_semihosting_fileio_command,
1629 .mode = COMMAND_EXEC,
1630 .usage = "['enable'|'disable']",
1631 .help = "activate support for semihosting fileio operations",
1634 "semihosting_resexit",
1635 .handler = handle_common_semihosting_resumable_exit_command,
1636 .mode = COMMAND_EXEC,
1637 .usage = "['enable'|'disable']",
1638 .help = "activate support for semihosting resumable exit",
1640 COMMAND_REGISTRATION_DONE