GDB fileIO stdout support
[openocd.git] / src / target / semihosting_common.c
blob59207897a4537b2c527d07a52a9b8b2a078d2f65
1 /***************************************************************************
2 * Copyright (C) 2018 by Liviu Ionescu *
3 * <ilg@livius.net> *
4 * *
5 * Copyright (C) 2018 by Marvell Technology Group Ltd. *
6 * Written by Nicolas Pitre <nico@marvell.com> *
7 * *
8 * Copyright (C) 2010 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * Copyright (C) 2016 by Square, Inc. *
12 * Steven Stallion <stallion@squareup.com> *
13 * *
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. *
18 * *
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. *
23 * *
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 ***************************************************************************/
28 /**
29 * @file
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
40 * from ARM Ltd.
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
47 #include "target.h"
48 #include "target_type.h"
49 #include "semihosting_common.h"
51 #include <helper/binarybuffer.h>
52 #include <helper/log.h>
53 #include <sys/stat.h>
55 static const int open_modeflags[12] = {
56 O_RDONLY,
57 O_RDONLY | O_BINARY,
58 O_RDWR,
59 O_RDWR | O_BINARY,
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,
76 uint8_t *fields);
77 static int semihosting_write_fields(struct target *target, size_t number,
78 uint8_t *fields);
79 static uint64_t semihosting_get_field(struct target *target, size_t index,
80 uint8_t *fields);
81 static void semihosting_set_field(struct target *target, uint64_t value,
82 size_t index,
83 uint8_t *fields);
85 /* Attempts to include gdb_server.h failed. */
86 extern int gdb_actual_connections;
88 /**
89 * Initialize common semihosting support.
91 * @param target Pointer to the target to initialize.
92 * @return An error status if there is a problem during initialization.
94 int semihosting_common_init(struct target *target, void *setup,
95 void *post_result)
97 LOG_DEBUG(" ");
99 target->fileio_info = malloc(sizeof(*target->fileio_info));
100 if (target->fileio_info == NULL) {
101 LOG_ERROR("out of memory");
102 return ERROR_FAIL;
104 memset(target->fileio_info, 0, sizeof(*target->fileio_info));
106 struct semihosting *semihosting;
107 semihosting = malloc(sizeof(*target->semihosting));
108 if (semihosting == NULL) {
109 LOG_ERROR("out of memory");
110 return ERROR_FAIL;
113 semihosting->is_active = false;
114 semihosting->is_fileio = false;
115 semihosting->hit_fileio = false;
116 semihosting->is_resumable = false;
117 semihosting->has_resumable_exit = false;
118 semihosting->word_size_bytes = 0;
119 semihosting->op = -1;
120 semihosting->param = 0;
121 semihosting->result = -1;
122 semihosting->sys_errno = -1;
123 semihosting->cmdline = NULL;
125 /* If possible, update it in setup(). */
126 semihosting->setup_time = clock();
128 semihosting->setup = setup;
129 semihosting->post_result = post_result;
131 target->semihosting = semihosting;
133 target->type->get_gdb_fileio_info = semihosting_common_fileio_info;
134 target->type->gdb_fileio_end = semihosting_common_fileio_end;
136 return ERROR_OK;
140 * Portable implementation of ARM semihosting calls.
141 * Performs the currently pending semihosting operation
142 * encoded in target->semihosting.
144 int semihosting_common(struct target *target)
146 struct semihosting *semihosting = target->semihosting;
147 if (!semihosting) {
148 /* Silently ignore if the semhosting field was not set. */
149 return ERROR_OK;
152 struct gdb_fileio_info *fileio_info = target->fileio_info;
155 * By default return an error.
156 * The actual result must be set by each function
158 semihosting->result = -1;
160 /* Most operations are resumable, except the two exit calls. */
161 semihosting->is_resumable = true;
163 int retval;
165 /* Enough space to hold 4 long words. */
166 uint8_t fields[4*8];
168 LOG_DEBUG("op=0x%x, param=0x%" PRIx64, (int)semihosting->op,
169 semihosting->param);
171 switch (semihosting->op) {
173 case SEMIHOSTING_SYS_CLOCK: /* 0x10 */
175 * Returns the number of centiseconds (hundredths of a second)
176 * since the execution started.
178 * Values returned can be of limited use for some benchmarking
179 * purposes because of communication overhead or other
180 * agent-specific factors. For example, with a debug hardware
181 * unit the request is passed back to the host for execution.
182 * This can lead to unpredictable delays in transmission and
183 * process scheduling.
185 * Use this function to calculate time intervals, by calculating
186 * differences between intervals with and without the code
187 * sequence to be timed.
189 * Entry
190 * The PARAMETER REGISTER must contain 0. There are no other
191 * parameters.
193 * Return
194 * On exit, the RETURN REGISTER contains:
195 * - The number of centiseconds since some arbitrary start
196 * point, if the call is successful.
197 * - –1 if the call is not successful. For example, because
198 * of a communications error.
201 clock_t delta = clock() - semihosting->setup_time;
203 semihosting->result = delta / (CLOCKS_PER_SEC / 100);
205 break;
207 case SEMIHOSTING_SYS_CLOSE: /* 0x02 */
209 * Closes a file on the host system. The handle must reference
210 * a file that was opened with SYS_OPEN.
212 * Entry
213 * On entry, the PARAMETER REGISTER contains a pointer to a
214 * one-field argument block:
215 * - field 1 Contains a handle for an open file.
217 * Return
218 * On exit, the RETURN REGISTER contains:
219 * - 0 if the call is successful
220 * - –1 if the call is not successful.
222 retval = semihosting_read_fields(target, 1, fields);
223 if (retval != ERROR_OK)
224 return retval;
225 else {
226 int fd = semihosting_get_field(target, 0, fields);
227 if (semihosting->is_fileio) {
228 if (fd == 0 || fd == 1 || fd == 2) {
229 semihosting->result = 0;
230 break;
232 semihosting->hit_fileio = true;
233 fileio_info->identifier = "close";
234 fileio_info->param_1 = fd;
235 } else {
236 semihosting->result = close(fd);
237 semihosting->sys_errno = errno;
239 LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result);
242 break;
244 case SEMIHOSTING_SYS_ERRNO: /* 0x13 */
246 * Returns the value of the C library errno variable that is
247 * associated with the semihosting implementation. The errno
248 * variable can be set by a number of C library semihosted
249 * functions, including:
250 * - SYS_REMOVE
251 * - SYS_OPEN
252 * - SYS_CLOSE
253 * - SYS_READ
254 * - SYS_WRITE
255 * - SYS_SEEK.
257 * Whether errno is set or not, and to what value, is entirely
258 * host-specific, except where the ISO C standard defines the
259 * behavior.
261 * Entry
262 * There are no parameters. The PARAMETER REGISTER must be 0.
264 * Return
265 * On exit, the RETURN REGISTER contains the value of the C
266 * library errno variable.
268 semihosting->result = semihosting->sys_errno;
269 break;
271 case SEMIHOSTING_SYS_EXIT: /* 0x18 */
273 * Note: SYS_EXIT was called angel_SWIreason_ReportException in
274 * previous versions of the documentation.
276 * An application calls this operation to report an exception
277 * to the debugger directly. The most common use is to report
278 * that execution has completed, using ADP_Stopped_ApplicationExit.
280 * Note: This semihosting operation provides no means for 32-bit
281 * callers to indicate an application exit with a specified exit
282 * code. Semihosting callers may prefer to check for the presence
283 * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
284 * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
285 * is available.
287 * Entry (32-bit)
288 * On entry, the PARAMETER register is set to a reason code
289 * describing the cause of the trap. Not all semihosting client
290 * implementations will necessarily trap every corresponding
291 * event. Important reason codes are:
293 * - ADP_Stopped_ApplicationExit 0x20026
294 * - ADP_Stopped_RunTimeErrorUnknown 0x20023
296 * Entry (64-bit)
297 * On entry, the PARAMETER REGISTER contains a pointer to a
298 * two-field argument block:
299 * - field 1 The exception type, which is one of the set of
300 * reason codes in the above tables.
301 * - field 2 A subcode, whose meaning depends on the reason
302 * code in field 1.
303 * In particular, if field 1 is ADP_Stopped_ApplicationExit
304 * then field 2 is an exit status code, as passed to the C
305 * standard library exit() function. A simulator receiving
306 * this request must notify a connected debugger, if present,
307 * and then exit with the specified status.
309 * Return
310 * No return is expected from these calls. However, it is
311 * possible for the debugger to request that the application
312 * continues by performing an RDI_Execute request or equivalent.
313 * In this case, execution continues with the registers as they
314 * were on entry to the operation, or as subsequently modified
315 * by the debugger.
317 if (semihosting->word_size_bytes == 8) {
318 retval = semihosting_read_fields(target, 2, fields);
319 if (retval != ERROR_OK)
320 return retval;
321 else {
322 int type = semihosting_get_field(target, 0, fields);
323 int code = semihosting_get_field(target, 1, fields);
325 if (type == ADP_STOPPED_APPLICATION_EXIT) {
326 if (!gdb_actual_connections)
327 exit(code);
328 else {
329 fprintf(stderr,
330 "semihosting: *** application exited with %d ***\n",
331 code);
333 } else {
334 fprintf(stderr,
335 "semihosting: application exception %#x\n",
336 type);
339 } else {
340 if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
341 if (!gdb_actual_connections)
342 exit(0);
343 else {
344 fprintf(stderr,
345 "semihosting: *** application exited normally ***\n");
347 } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
348 /* Chosen more or less arbitrarly to have a nicer message,
349 * otherwise all other return the same exit code 1. */
350 if (!gdb_actual_connections)
351 exit(1);
352 else {
353 fprintf(stderr,
354 "semihosting: *** application exited with error ***\n");
356 } else {
357 if (!gdb_actual_connections)
358 exit(1);
359 else {
360 fprintf(stderr,
361 "semihosting: application exception %#x\n",
362 (unsigned) semihosting->param);
366 if (!semihosting->has_resumable_exit) {
367 semihosting->is_resumable = false;
368 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
370 break;
372 case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */
374 * This operation is only supported if the semihosting extension
375 * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
376 * reported using feature byte 0, bit 0. If this extension is
377 * supported, then the implementation provides a means to
378 * report a normal exit with a nonzero exit status in both 32-bit
379 * and 64-bit semihosting APIs.
381 * The implementation must provide the semihosting call
382 * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
384 * SYS_EXIT_EXTENDED is used by an application to report an
385 * exception or exit to the debugger directly. The most common
386 * use is to report that execution has completed, using
387 * ADP_Stopped_ApplicationExit.
389 * Entry
390 * On entry, the PARAMETER REGISTER contains a pointer to a
391 * two-field argument block:
392 * - field 1 The exception type, which should be one of the set
393 * of reason codes that are documented for the SYS_EXIT
394 * (0x18) call. For example, ADP_Stopped_ApplicationExit.
395 * - field 2 A subcode, whose meaning depends on the reason
396 * code in field 1. In particular, if field 1 is
397 * ADP_Stopped_ApplicationExit then field 2 is an exit status
398 * code, as passed to the C standard library exit() function.
399 * A simulator receiving this request must notify a connected
400 * debugger, if present, and then exit with the specified status.
402 * Return
403 * No return is expected from these calls.
405 * For the A64 API, this call is identical to the behavior of
406 * the mandatory SYS_EXIT (0x18) call. If this extension is
407 * supported, then both calls must be implemented.
409 retval = semihosting_read_fields(target, 2, fields);
410 if (retval != ERROR_OK)
411 return retval;
412 else {
413 int type = semihosting_get_field(target, 0, fields);
414 int code = semihosting_get_field(target, 1, fields);
416 if (type == ADP_STOPPED_APPLICATION_EXIT) {
417 if (!gdb_actual_connections)
418 exit(code);
419 else {
420 fprintf(stderr,
421 "semihosting: *** application exited with %d ***\n",
422 code);
424 } else {
425 fprintf(stderr, "semihosting: exception %#x\n",
426 type);
429 if (!semihosting->has_resumable_exit) {
430 semihosting->is_resumable = false;
431 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
433 break;
435 case SEMIHOSTING_SYS_FLEN: /* 0x0C */
437 * Returns the length of a specified file.
439 * Entry
440 * On entry, the PARAMETER REGISTER contains a pointer to a
441 * one-field argument block:
442 * - field 1 A handle for a previously opened, seekable file
443 * object.
445 * Return
446 * On exit, the RETURN REGISTER contains:
447 * - The current length of the file object, if the call is
448 * successful.
449 * - –1 if an error occurs.
451 if (semihosting->is_fileio) {
452 semihosting->result = -1;
453 semihosting->sys_errno = EINVAL;
455 retval = semihosting_read_fields(target, 1, fields);
456 if (retval != ERROR_OK)
457 return retval;
458 else {
459 int fd = semihosting_get_field(target, 0, fields);
460 struct stat buf;
461 semihosting->result = fstat(fd, &buf);
462 if (semihosting->result == -1) {
463 semihosting->sys_errno = errno;
464 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
465 break;
467 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
468 semihosting->result = buf.st_size;
470 break;
472 case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */
474 * Returns the command line that is used for the call to the
475 * executable, that is, argc and argv.
477 * Entry
478 * On entry, the PARAMETER REGISTER points to a two-field data
479 * block to be used for returning the command string and its length:
480 * - field 1 A pointer to a buffer of at least the size that is
481 * specified in field 2.
482 * - field 2 The length of the buffer in bytes.
484 * Return
485 * On exit:
486 * If the call is successful, then the RETURN REGISTER contains 0,
487 * the PARAMETER REGISTER is unchanged, and the data block is
488 * updated as follows:
489 * - field 1 A pointer to a null-terminated string of the command
490 * line.
491 * - field 2 The length of the string in bytes.
492 * If the call is not successful, then the RETURN REGISTER
493 * contains -1.
495 * Note: The semihosting implementation might impose limits on
496 * the maximum length of the string that can be transferred.
497 * However, the implementation must be able to support a
498 * command-line length of at least 80 bytes.
500 retval = semihosting_read_fields(target, 2, fields);
501 if (retval != ERROR_OK)
502 return retval;
503 else {
504 uint64_t addr = semihosting_get_field(target, 0, fields);
505 size_t size = semihosting_get_field(target, 1, fields);
507 char *arg = semihosting->cmdline != NULL ?
508 semihosting->cmdline : "";
509 uint32_t len = strlen(arg) + 1;
510 if (len > size)
511 semihosting->result = -1;
512 else {
513 semihosting_set_field(target, len, 1, fields);
514 retval = target_write_buffer(target, addr, len,
515 (uint8_t *)arg);
516 if (retval != ERROR_OK)
517 return retval;
518 semihosting->result = 0;
520 retval = semihosting_write_fields(target, 2, fields);
521 if (retval != ERROR_OK)
522 return retval;
524 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg,
525 (int)semihosting->result);
527 break;
529 case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */
531 * Returns the system stack and heap parameters.
533 * Entry
534 * On entry, the PARAMETER REGISTER contains the address of a
535 * pointer to a four-field data block. The contents of the data
536 * block are filled by the function. The following C-like
537 * pseudocode describes the layout of the block:
538 * struct block {
539 * void* heap_base;
540 * void* heap_limit;
541 * void* stack_base;
542 * void* stack_limit;
543 * };
545 * Return
546 * On exit, the PARAMETER REGISTER is unchanged and the data
547 * block has been updated.
549 retval = semihosting_read_fields(target, 1, fields);
550 if (retval != ERROR_OK)
551 return retval;
552 else {
553 uint64_t addr = semihosting_get_field(target, 0, fields);
554 /* tell the remote we have no idea */
555 memset(fields, 0, 4 * semihosting->word_size_bytes);
556 retval = target_write_memory(target, addr, 4,
557 semihosting->word_size_bytes,
558 fields);
559 if (retval != ERROR_OK)
560 return retval;
561 semihosting->result = 0;
563 break;
565 case SEMIHOSTING_SYS_ISERROR: /* 0x08 */
567 * Determines whether the return code from another semihosting
568 * call is an error status or not.
570 * This call is passed a parameter block containing the error
571 * code to examine.
573 * Entry
574 * On entry, the PARAMETER REGISTER contains a pointer to a
575 * one-field data block:
576 * - field 1 The required status word to check.
578 * Return
579 * On exit, the RETURN REGISTER contains:
580 * - 0 if the status field is not an error indication
581 * - A nonzero value if the status field is an error indication.
583 retval = semihosting_read_fields(target, 1, fields);
584 if (retval != ERROR_OK)
585 return retval;
587 uint64_t code = semihosting_get_field(target, 0, fields);
588 semihosting->result = (code != 0);
589 break;
591 case SEMIHOSTING_SYS_ISTTY: /* 0x09 */
593 * Checks whether a file is connected to an interactive device.
595 * Entry
596 * On entry, the PARAMETER REGISTER contains a pointer to a
597 * one-field argument block:
598 * field 1 A handle for a previously opened file object.
600 * Return
601 * On exit, the RETURN REGISTER contains:
602 * - 1 if the handle identifies an interactive device.
603 * - 0 if the handle identifies a file.
604 * - A value other than 1 or 0 if an error occurs.
606 if (semihosting->is_fileio) {
607 semihosting->hit_fileio = true;
608 fileio_info->identifier = "isatty";
609 fileio_info->param_1 = semihosting->param;
610 } else {
611 retval = semihosting_read_fields(target, 1, fields);
612 if (retval != ERROR_OK)
613 return retval;
614 int fd = semihosting_get_field(target, 0, fields);
615 semihosting->result = isatty(fd);
616 LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result);
618 break;
620 case SEMIHOSTING_SYS_OPEN: /* 0x01 */
622 * Opens a file on the host system.
624 * The file path is specified either as relative to the current
625 * directory of the host process, or absolute, using the path
626 * conventions of the host operating system.
628 * Semihosting implementations must support opening the special
629 * path name :semihosting-features as part of the semihosting
630 * extensions reporting mechanism.
632 * ARM targets interpret the special path name :tt as meaning
633 * the console input stream, for an open-read or the console
634 * output stream, for an open-write. Opening these streams is
635 * performed as part of the standard startup code for those
636 * applications that reference the C stdio streams. The
637 * semihosting extension SH_EXT_STDOUT_STDERR allows the
638 * semihosting caller to open separate output streams
639 * corresponding to stdout and stderr. This extension is
640 * reported using feature byte 0, bit 1. Use SYS_OPEN with
641 * the special path name :semihosting-features to access the
642 * feature bits.
644 * If this extension is supported, the implementation must
645 * support the following additional semantics to SYS_OPEN:
646 * - If the special path name :tt is opened with an fopen
647 * mode requesting write access (w, wb, w+, or w+b), then
648 * this is a request to open stdout.
649 * - If the special path name :tt is opened with a mode
650 * requesting append access (a, ab, a+, or a+b), then this is
651 * a request to open stderr.
653 * Entry
654 * On entry, the PARAMETER REGISTER contains a pointer to a
655 * three-field argument block:
656 * - field 1 A pointer to a null-terminated string containing
657 * a file or device name.
658 * - field 2 An integer that specifies the file opening mode.
659 * - field 3 An integer that gives the length of the string
660 * pointed to by field 1.
662 * The length does not include the terminating null character
663 * that must be present.
665 * Return
666 * On exit, the RETURN REGISTER contains:
667 * - A nonzero handle if the call is successful.
668 * - –1 if the call is not successful.
670 retval = semihosting_read_fields(target, 3, fields);
671 if (retval != ERROR_OK)
672 return retval;
673 else {
674 uint64_t addr = semihosting_get_field(target, 0, fields);
675 uint32_t mode = semihosting_get_field(target, 1, fields);
676 size_t len = semihosting_get_field(target, 2, fields);
678 if (mode > 11) {
679 semihosting->result = -1;
680 semihosting->sys_errno = EINVAL;
681 break;
683 uint8_t *fn = malloc(len+1);
684 if (!fn) {
685 semihosting->result = -1;
686 semihosting->sys_errno = ENOMEM;
687 } else {
688 retval = target_read_memory(target, addr, 1, len, fn);
689 if (retval != ERROR_OK) {
690 free(fn);
691 return retval;
693 fn[len] = 0;
694 /* TODO: implement the :semihosting-features special file.
695 * */
696 if (semihosting->is_fileio) {
697 if (strcmp((char *)fn, ":semihosting-features") == 0) {
698 semihosting->result = -1;
699 semihosting->sys_errno = EINVAL;
700 } else if (strcmp((char *)fn, ":tt") == 0) {
701 if (mode == 0)
702 semihosting->result = 0;
703 else if (mode == 4)
704 semihosting->result = 1;
705 else if (mode == 8)
706 semihosting->result = 2;
707 else
708 semihosting->result = -1;
709 } else {
710 semihosting->hit_fileio = true;
711 fileio_info->identifier = "open";
712 fileio_info->param_1 = addr;
713 fileio_info->param_2 = len;
714 fileio_info->param_3 = open_modeflags[mode];
715 fileio_info->param_4 = 0644;
717 } else {
718 if (strcmp((char *)fn, ":tt") == 0) {
719 /* Mode is:
720 * - 0-3 ("r") for stdin,
721 * - 4-7 ("w") for stdout,
722 * - 8-11 ("a") for stderr */
723 if (mode < 4) {
724 semihosting->result = dup(
725 STDIN_FILENO);
726 semihosting->sys_errno = errno;
727 LOG_DEBUG("dup(STDIN)=%d",
728 (int)semihosting->result);
729 } else if (mode < 8) {
730 semihosting->result = dup(
731 STDOUT_FILENO);
732 semihosting->sys_errno = errno;
733 LOG_DEBUG("dup(STDOUT)=%d",
734 (int)semihosting->result);
735 } else {
736 semihosting->result = dup(
737 STDERR_FILENO);
738 semihosting->sys_errno = errno;
739 LOG_DEBUG("dup(STDERR)=%d",
740 (int)semihosting->result);
742 } else {
743 /* cygwin requires the permission setting
744 * otherwise it will fail to reopen a previously
745 * written file */
746 semihosting->result = open((char *)fn,
747 open_modeflags[mode],
748 0644);
749 semihosting->sys_errno = errno;
750 LOG_DEBUG("open('%s')=%d", fn,
751 (int)semihosting->result);
754 free(fn);
757 break;
759 case SEMIHOSTING_SYS_READ: /* 0x06 */
761 * Reads the contents of a file into a buffer. The file position
762 * is specified either:
763 * - Explicitly by a SYS_SEEK.
764 * - Implicitly one byte beyond the previous SYS_READ or
765 * SYS_WRITE request.
767 * The file position is at the start of the file when it is
768 * opened, and is lost when the file is closed. Perform the
769 * file operation as a single action whenever possible. For
770 * example, do not split a read of 16KB into four 4KB chunks
771 * unless there is no alternative.
773 * Entry
774 * On entry, the PARAMETER REGISTER contains a pointer to a
775 * three-field data block:
776 * - field 1 Contains a handle for a file previously opened
777 * with SYS_OPEN.
778 * - field 2 Points to a buffer.
779 * - field 3 Contains the number of bytes to read to the buffer
780 * from the file.
782 * Return
783 * On exit, the RETURN REGISTER contains the number of bytes not
784 * filled in the buffer (buffer_length - bytes_read) as follows:
785 * - If the RETURN REGISTER is 0, the entire buffer was
786 * successfully filled.
787 * - If the RETURN REGISTER is the same as field 3, no bytes
788 * were read (EOF can be assumed).
789 * - If the RETURN REGISTER contains a value smaller than
790 * field 3, the read succeeded but the buffer was only partly
791 * filled. For interactive devices, this is the most common
792 * return value.
794 retval = semihosting_read_fields(target, 3, fields);
795 if (retval != ERROR_OK)
796 return retval;
797 else {
798 int fd = semihosting_get_field(target, 0, fields);
799 uint64_t addr = semihosting_get_field(target, 1, fields);
800 size_t len = semihosting_get_field(target, 2, fields);
801 if (semihosting->is_fileio) {
802 semihosting->hit_fileio = true;
803 fileio_info->identifier = "read";
804 fileio_info->param_1 = fd;
805 fileio_info->param_2 = addr;
806 fileio_info->param_3 = len;
807 } else {
808 uint8_t *buf = malloc(len);
809 if (!buf) {
810 semihosting->result = -1;
811 semihosting->sys_errno = ENOMEM;
812 } else {
813 semihosting->result = read(fd, buf, len);
814 semihosting->sys_errno = errno;
815 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
817 addr,
818 len,
819 (int)semihosting->result);
820 if (semihosting->result >= 0) {
821 retval = target_write_buffer(target, addr,
822 semihosting->result,
823 buf);
824 if (retval != ERROR_OK) {
825 free(buf);
826 return retval;
828 /* the number of bytes NOT filled in */
829 semihosting->result = len -
830 semihosting->result;
832 free(buf);
836 break;
838 case SEMIHOSTING_SYS_READC: /* 0x07 */
840 * Reads a byte from the console.
842 * Entry
843 * The PARAMETER REGISTER must contain 0. There are no other
844 * parameters or values possible.
846 * Return
847 * On exit, the RETURN REGISTER contains the byte read from
848 * the console.
850 if (semihosting->is_fileio) {
851 LOG_ERROR("SYS_READC not supported by semihosting fileio");
852 return ERROR_FAIL;
854 semihosting->result = getchar();
855 LOG_DEBUG("getchar()=%d", (int)semihosting->result);
856 break;
858 case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
860 * Deletes a specified file on the host filing system.
862 * Entry
863 * On entry, the PARAMETER REGISTER contains a pointer to a
864 * two-field argument block:
865 * - field 1 Points to a null-terminated string that gives the
866 * path name of the file to be deleted.
867 * - field 2 The length of the string.
869 * Return
870 * On exit, the RETURN REGISTER contains:
871 * - 0 if the delete is successful
872 * - A nonzero, host-specific error code if the delete fails.
874 retval = semihosting_read_fields(target, 2, fields);
875 if (retval != ERROR_OK)
876 return retval;
877 else {
878 uint64_t addr = semihosting_get_field(target, 0, fields);
879 size_t len = semihosting_get_field(target, 1, fields);
880 if (semihosting->is_fileio) {
881 semihosting->hit_fileio = true;
882 fileio_info->identifier = "unlink";
883 fileio_info->param_1 = addr;
884 fileio_info->param_2 = len;
885 } else {
886 uint8_t *fn = malloc(len+1);
887 if (!fn) {
888 semihosting->result = -1;
889 semihosting->sys_errno = ENOMEM;
890 } else {
891 retval =
892 target_read_memory(target, addr, 1, len,
893 fn);
894 if (retval != ERROR_OK) {
895 free(fn);
896 return retval;
898 fn[len] = 0;
899 semihosting->result = remove((char *)fn);
900 semihosting->sys_errno = errno;
901 LOG_DEBUG("remove('%s')=%d", fn,
902 (int)semihosting->result);
904 free(fn);
908 break;
910 case SEMIHOSTING_SYS_RENAME: /* 0x0F */
912 * Renames a specified file.
914 * Entry
915 * On entry, the PARAMETER REGISTER contains a pointer to a
916 * four-field data block:
917 * - field 1 A pointer to the name of the old file.
918 * - field 2 The length of the old filename.
919 * - field 3 A pointer to the new filename.
920 * - field 4 The length of the new filename. Both strings are
921 * null-terminated.
923 * Return
924 * On exit, the RETURN REGISTER contains:
925 * - 0 if the rename is successful.
926 * - A nonzero, host-specific error code if the rename fails.
928 retval = semihosting_read_fields(target, 4, fields);
929 if (retval != ERROR_OK)
930 return retval;
931 else {
932 uint64_t addr1 = semihosting_get_field(target, 0, fields);
933 size_t len1 = semihosting_get_field(target, 1, fields);
934 uint64_t addr2 = semihosting_get_field(target, 2, fields);
935 size_t len2 = semihosting_get_field(target, 3, fields);
936 if (semihosting->is_fileio) {
937 semihosting->hit_fileio = true;
938 fileio_info->identifier = "rename";
939 fileio_info->param_1 = addr1;
940 fileio_info->param_2 = len1;
941 fileio_info->param_3 = addr2;
942 fileio_info->param_4 = len2;
943 } else {
944 uint8_t *fn1 = malloc(len1+1);
945 uint8_t *fn2 = malloc(len2+1);
946 if (!fn1 || !fn2) {
947 semihosting->result = -1;
948 semihosting->sys_errno = ENOMEM;
949 } else {
950 retval = target_read_memory(target, addr1, 1, len1,
951 fn1);
952 if (retval != ERROR_OK) {
953 free(fn1);
954 free(fn2);
955 return retval;
957 retval = target_read_memory(target, addr2, 1, len2,
958 fn2);
959 if (retval != ERROR_OK) {
960 free(fn1);
961 free(fn2);
962 return retval;
964 fn1[len1] = 0;
965 fn2[len2] = 0;
966 semihosting->result = rename((char *)fn1,
967 (char *)fn2);
968 semihosting->sys_errno = errno;
969 LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2,
970 (int)semihosting->result);
972 free(fn1);
973 free(fn2);
977 break;
979 case SEMIHOSTING_SYS_SEEK: /* 0x0A */
981 * Seeks to a specified position in a file using an offset
982 * specified from the start of the file. The file is assumed
983 * to be a byte array and the offset is given in bytes.
985 * Entry
986 * On entry, the PARAMETER REGISTER contains a pointer to a
987 * two-field data block:
988 * - field 1 A handle for a seekable file object.
989 * - field 2 The absolute byte position to seek to.
991 * Return
992 * On exit, the RETURN REGISTER contains:
993 * - 0 if the request is successful.
994 * - A negative value if the request is not successful.
995 * Use SYS_ERRNO to read the value of the host errno variable
996 * describing the error.
998 * Note: The effect of seeking outside the current extent of
999 * the file object is undefined.
1001 retval = semihosting_read_fields(target, 2, fields);
1002 if (retval != ERROR_OK)
1003 return retval;
1004 else {
1005 int fd = semihosting_get_field(target, 0, fields);
1006 off_t pos = semihosting_get_field(target, 1, fields);
1007 if (semihosting->is_fileio) {
1008 semihosting->hit_fileio = true;
1009 fileio_info->identifier = "lseek";
1010 fileio_info->param_1 = fd;
1011 fileio_info->param_2 = pos;
1012 fileio_info->param_3 = SEEK_SET;
1013 } else {
1014 semihosting->result = lseek(fd, pos, SEEK_SET);
1015 semihosting->sys_errno = errno;
1016 LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos,
1017 (int)semihosting->result);
1018 if (semihosting->result == pos)
1019 semihosting->result = 0;
1022 break;
1024 case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1026 * Passes a command to the host command-line interpreter.
1027 * This enables you to execute a system command such as dir,
1028 * ls, or pwd. The terminal I/O is on the host, and is not
1029 * visible to the target.
1031 * Entry
1032 * On entry, the PARAMETER REGISTER contains a pointer to a
1033 * two-field argument block:
1034 * - field 1 Points to a string to be passed to the host
1035 * command-line interpreter.
1036 * - field 2 The length of the string.
1038 * Return
1039 * On exit, the RETURN REGISTER contains the return status.
1042 /* Provide SYS_SYSTEM functionality. Uses the
1043 * libc system command, there may be a reason *NOT*
1044 * to use this, but as I can't think of one, I
1045 * implemented it this way.
1047 retval = semihosting_read_fields(target, 2, fields);
1048 if (retval != ERROR_OK)
1049 return retval;
1050 else {
1051 uint64_t addr = semihosting_get_field(target, 0, fields);
1052 size_t len = semihosting_get_field(target, 1, fields);
1053 if (semihosting->is_fileio) {
1054 semihosting->hit_fileio = true;
1055 fileio_info->identifier = "system";
1056 fileio_info->param_1 = addr;
1057 fileio_info->param_2 = len;
1058 } else {
1059 uint8_t *cmd = malloc(len+1);
1060 if (!cmd) {
1061 semihosting->result = -1;
1062 semihosting->sys_errno = ENOMEM;
1063 } else {
1064 retval = target_read_memory(target,
1065 addr,
1067 len,
1068 cmd);
1069 if (retval != ERROR_OK) {
1070 free(cmd);
1071 return retval;
1072 } else {
1073 cmd[len] = 0;
1074 semihosting->result = system(
1075 (const char *)cmd);
1076 LOG_DEBUG("system('%s')=%d",
1077 cmd,
1078 (int)semihosting->result);
1081 free(cmd);
1085 break;
1087 case SEMIHOSTING_SYS_TIME: /* 0x11 */
1089 * Returns the number of seconds since 00:00 January 1, 1970.
1090 * This value is real-world time, regardless of any debug agent
1091 * configuration.
1093 * Entry
1094 * There are no parameters.
1096 * Return
1097 * On exit, the RETURN REGISTER contains the number of seconds.
1099 semihosting->result = time(NULL);
1100 break;
1102 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1104 * Writes the contents of a buffer to a specified file at the
1105 * current file position. The file position is specified either:
1106 * - Explicitly, by a SYS_SEEK.
1107 * - Implicitly as one byte beyond the previous SYS_READ or
1108 * SYS_WRITE request.
1110 * The file position is at the start of the file when the file
1111 * is opened, and is lost when the file is closed.
1113 * Perform the file operation as a single action whenever
1114 * possible. For example, do not split a write of 16KB into
1115 * four 4KB chunks unless there is no alternative.
1117 * Entry
1118 * On entry, the PARAMETER REGISTER contains a pointer to a
1119 * three-field data block:
1120 * - field 1 Contains a handle for a file previously opened
1121 * with SYS_OPEN.
1122 * - field 2 Points to the memory containing the data to be written.
1123 * - field 3 Contains the number of bytes to be written from
1124 * the buffer to the file.
1126 * Return
1127 * On exit, the RETURN REGISTER contains:
1128 * - 0 if the call is successful.
1129 * - The number of bytes that are not written, if there is an error.
1131 retval = semihosting_read_fields(target, 3, fields);
1132 if (retval != ERROR_OK)
1133 return retval;
1134 else {
1135 int fd = semihosting_get_field(target, 0, fields);
1136 uint64_t addr = semihosting_get_field(target, 1, fields);
1137 size_t len = semihosting_get_field(target, 2, fields);
1138 if (semihosting->is_fileio) {
1139 semihosting->hit_fileio = true;
1140 fileio_info->identifier = "write";
1141 fileio_info->param_1 = fd;
1142 fileio_info->param_2 = addr;
1143 fileio_info->param_3 = len;
1144 } else {
1145 uint8_t *buf = malloc(len);
1146 if (!buf) {
1147 semihosting->result = -1;
1148 semihosting->sys_errno = ENOMEM;
1149 } else {
1150 retval = target_read_buffer(target, addr, len, buf);
1151 if (retval != ERROR_OK) {
1152 free(buf);
1153 return retval;
1155 semihosting->result = write(fd, buf, len);
1156 semihosting->sys_errno = errno;
1157 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
1159 addr,
1160 len,
1161 (int)semihosting->result);
1162 if (semihosting->result >= 0) {
1163 /* The number of bytes that are NOT written.
1164 * */
1165 semihosting->result = len -
1166 semihosting->result;
1169 free(buf);
1173 break;
1175 case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1177 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1178 * to the debug channel. When executed under a semihosting
1179 * debugger, the character appears on the host debugger console.
1181 * Entry
1182 * On entry, the PARAMETER REGISTER contains a pointer to the
1183 * character.
1185 * Return
1186 * None. The RETURN REGISTER is corrupted.
1188 if (semihosting->is_fileio) {
1189 semihosting->hit_fileio = true;
1190 fileio_info->identifier = "write";
1191 fileio_info->param_1 = 1;
1192 fileio_info->param_2 = semihosting->param;
1193 fileio_info->param_3 = 1;
1194 } else {
1195 uint64_t addr = semihosting->param;
1196 unsigned char c;
1197 retval = target_read_memory(target, addr, 1, 1, &c);
1198 if (retval != ERROR_OK)
1199 return retval;
1200 putchar(c);
1201 semihosting->result = 0;
1203 break;
1205 case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1207 * Writes a null-terminated string to the debug channel.
1208 * When executed under a semihosting debugger, the characters
1209 * appear on the host debugger console.
1211 * Entry
1212 * On entry, the PARAMETER REGISTER contains a pointer to the
1213 * first byte of the string.
1215 * Return
1216 * None. The RETURN REGISTER is corrupted.
1218 if (semihosting->is_fileio) {
1219 size_t count = 0;
1220 uint64_t addr = semihosting->param;
1221 for (;; addr++) {
1222 unsigned char c;
1223 retval = target_read_memory(target, addr, 1, 1, &c);
1224 if (retval != ERROR_OK)
1225 return retval;
1226 if (c == '\0')
1227 break;
1228 count++;
1230 semihosting->hit_fileio = true;
1231 fileio_info->identifier = "write";
1232 fileio_info->param_1 = 1;
1233 fileio_info->param_2 = semihosting->param;
1234 fileio_info->param_3 = count;
1235 } else {
1236 uint64_t addr = semihosting->param;
1237 do {
1238 unsigned char c;
1239 retval = target_read_memory(target, addr++, 1, 1, &c);
1240 if (retval != ERROR_OK)
1241 return retval;
1242 if (!c)
1243 break;
1244 putchar(c);
1245 } while (1);
1246 semihosting->result = 0;
1248 break;
1250 case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1252 * Returns the number of elapsed target ticks since execution
1253 * started.
1254 * Use SYS_TICKFREQ to determine the tick frequency.
1256 * Entry (32-bit)
1257 * On entry, the PARAMETER REGISTER points to a two-field data
1258 * block to be used for returning the number of elapsed ticks:
1259 * - field 1 The least significant field and is at the low address.
1260 * - field 2 The most significant field and is at the high address.
1262 * Entry (64-bit)
1263 * On entry the PARAMETER REGISTER points to a one-field data
1264 * block to be used for returning the number of elapsed ticks:
1265 * - field 1 The number of elapsed ticks as a 64-bit value.
1267 * Return
1268 * On exit:
1269 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1270 * REGISTER is unchanged, and the data block pointed to by the
1271 * PARAMETER REGISTER is filled in with the number of elapsed
1272 * ticks.
1273 * - On failure, the RETURN REGISTER contains -1, and the
1274 * PARAMETER REGISTER contains -1.
1276 * Note: Some semihosting implementations might not support this
1277 * semihosting operation, and they always return -1 in the
1278 * RETURN REGISTER.
1281 case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1283 * Returns the tick frequency.
1285 * Entry
1286 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1288 * Return
1289 * On exit, the RETURN REGISTER contains either:
1290 * - The number of ticks per second.
1291 * - –1 if the target does not know the value of one tick.
1293 * Note: Some semihosting implementations might not support
1294 * this semihosting operation, and they always return -1 in the
1295 * RETURN REGISTER.
1298 case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1300 * Returns a temporary name for a file identified by a system
1301 * file identifier.
1303 * Entry
1304 * On entry, the PARAMETER REGISTER contains a pointer to a
1305 * three-word argument block:
1306 * - field 1 A pointer to a buffer.
1307 * - field 2 A target identifier for this filename. Its value
1308 * must be an integer in the range 0-255.
1309 * - field 3 Contains the length of the buffer. The length must
1310 * be at least the value of L_tmpnam on the host system.
1312 * Return
1313 * On exit, the RETURN REGISTER contains:
1314 * - 0 if the call is successful.
1315 * - –1 if an error occurs.
1317 * The buffer pointed to by the PARAMETER REGISTER contains
1318 * the filename, prefixed with a suitable directory name.
1319 * If you use the same target identifier again, the same
1320 * filename is returned.
1322 * Note: The returned string must be null-terminated.
1325 default:
1326 fprintf(stderr, "semihosting: unsupported call %#x\n",
1327 (unsigned) semihosting->op);
1328 semihosting->result = -1;
1329 semihosting->sys_errno = ENOTSUP;
1332 if (!semihosting->hit_fileio) {
1333 retval = semihosting->post_result(target);
1334 if (retval != ERROR_OK) {
1335 LOG_ERROR("Failed to post semihosting result");
1336 return retval;
1340 return ERROR_OK;
1343 /* -------------------------------------------------------------------------
1344 * Local functions. */
1346 static int semihosting_common_fileio_info(struct target *target,
1347 struct gdb_fileio_info *fileio_info)
1349 struct semihosting *semihosting = target->semihosting;
1350 if (!semihosting)
1351 return ERROR_FAIL;
1354 * To avoid unnecessary duplication, semihosting prepares the
1355 * fileio_info structure out-of-band when the target halts. See
1356 * do_semihosting for more detail.
1358 if (!semihosting->is_fileio || !semihosting->hit_fileio)
1359 return ERROR_FAIL;
1361 return ERROR_OK;
1364 static int semihosting_common_fileio_end(struct target *target, int result,
1365 int fileio_errno, bool ctrl_c)
1367 struct gdb_fileio_info *fileio_info = target->fileio_info;
1368 struct semihosting *semihosting = target->semihosting;
1369 if (!semihosting)
1370 return ERROR_FAIL;
1372 /* clear pending status */
1373 semihosting->hit_fileio = false;
1375 semihosting->result = result;
1376 semihosting->sys_errno = fileio_errno;
1379 * Some fileio results do not match up with what the semihosting
1380 * operation expects; for these operations, we munge the results
1381 * below:
1383 switch (semihosting->op) {
1384 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1385 if (result < 0)
1386 semihosting->result = fileio_info->param_3;
1387 else
1388 semihosting->result = 0;
1389 break;
1391 case SEMIHOSTING_SYS_READ: /* 0x06 */
1392 if (result == (int)fileio_info->param_3)
1393 semihosting->result = 0;
1394 if (result <= 0)
1395 semihosting->result = fileio_info->param_3;
1396 break;
1398 case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1399 if (result > 0)
1400 semihosting->result = 0;
1401 break;
1404 return semihosting->post_result(target);
1408 * Read all fields of a command from target to buffer.
1410 static int semihosting_read_fields(struct target *target, size_t number,
1411 uint8_t *fields)
1413 struct semihosting *semihosting = target->semihosting;
1414 /* Use 4-byte multiples to trigger fast memory access. */
1415 return target_read_memory(target, semihosting->param, 4,
1416 number * (semihosting->word_size_bytes / 4), fields);
1420 * Write all fields of a command from buffer to target.
1422 static int semihosting_write_fields(struct target *target, size_t number,
1423 uint8_t *fields)
1425 struct semihosting *semihosting = target->semihosting;
1426 /* Use 4-byte multiples to trigger fast memory access. */
1427 return target_write_memory(target, semihosting->param, 4,
1428 number * (semihosting->word_size_bytes / 4), fields);
1432 * Extract a field from the buffer, considering register size and endianness.
1434 static uint64_t semihosting_get_field(struct target *target, size_t index,
1435 uint8_t *fields)
1437 struct semihosting *semihosting = target->semihosting;
1438 if (semihosting->word_size_bytes == 8)
1439 return target_buffer_get_u64(target, fields + (index * 8));
1440 else
1441 return target_buffer_get_u32(target, fields + (index * 4));
1445 * Store a field in the buffer, considering register size and endianness.
1447 static void semihosting_set_field(struct target *target, uint64_t value,
1448 size_t index,
1449 uint8_t *fields)
1451 struct semihosting *semihosting = target->semihosting;
1452 if (semihosting->word_size_bytes == 8)
1453 target_buffer_set_u64(target, fields + (index * 8), value);
1454 else
1455 target_buffer_set_u32(target, fields + (index * 4), value);
1459 /* -------------------------------------------------------------------------
1460 * Common semihosting commands handlers. */
1462 __COMMAND_HANDLER(handle_common_semihosting_command)
1464 struct target *target = get_current_target(CMD_CTX);
1466 if (target == NULL) {
1467 LOG_ERROR("No target selected");
1468 return ERROR_FAIL;
1471 struct semihosting *semihosting = target->semihosting;
1472 if (!semihosting) {
1473 command_print(CMD_CTX, "semihosting not supported for current target");
1474 return ERROR_FAIL;
1477 if (CMD_ARGC > 0) {
1478 int is_active;
1480 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1482 if (!target_was_examined(target)) {
1483 LOG_ERROR("Target not examined yet");
1484 return ERROR_FAIL;
1487 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1488 LOG_ERROR("Failed to Configure semihosting");
1489 return ERROR_FAIL;
1492 /* FIXME never let that "catch" be dropped! (???) */
1493 semihosting->is_active = is_active;
1496 command_print(CMD_CTX, "semihosting is %s",
1497 semihosting->is_active
1498 ? "enabled" : "disabled");
1500 return ERROR_OK;
1504 __COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1506 struct target *target = get_current_target(CMD_CTX);
1508 if (target == NULL) {
1509 LOG_ERROR("No target selected");
1510 return ERROR_FAIL;
1513 struct semihosting *semihosting = target->semihosting;
1514 if (!semihosting) {
1515 command_print(CMD_CTX, "semihosting not supported for current target");
1516 return ERROR_FAIL;
1519 if (!semihosting->is_active) {
1520 command_print(CMD_CTX, "semihosting not yet enabled for current target");
1521 return ERROR_FAIL;
1524 if (CMD_ARGC > 0)
1525 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1527 command_print(CMD_CTX, "semihosting fileio is %s",
1528 semihosting->is_fileio
1529 ? "enabled" : "disabled");
1531 return ERROR_OK;
1534 __COMMAND_HANDLER(handle_common_semihosting_cmdline)
1536 struct target *target = get_current_target(CMD_CTX);
1537 unsigned int i;
1539 if (target == NULL) {
1540 LOG_ERROR("No target selected");
1541 return ERROR_FAIL;
1544 struct semihosting *semihosting = target->semihosting;
1545 if (!semihosting) {
1546 command_print(CMD_CTX, "semihosting not supported for current target");
1547 return ERROR_FAIL;
1550 free(semihosting->cmdline);
1551 semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
1553 for (i = 1; i < CMD_ARGC; i++) {
1554 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
1555 if (cmdline == NULL)
1556 break;
1557 free(semihosting->cmdline);
1558 semihosting->cmdline = cmdline;
1561 command_print(CMD_CTX, "semihosting command line is [%s]",
1562 semihosting->cmdline);
1564 return ERROR_OK;
1567 __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
1569 struct target *target = get_current_target(CMD_CTX);
1571 if (target == NULL) {
1572 LOG_ERROR("No target selected");
1573 return ERROR_FAIL;
1576 struct semihosting *semihosting = target->semihosting;
1577 if (!semihosting) {
1578 command_print(CMD_CTX, "semihosting not supported for current target");
1579 return ERROR_FAIL;
1582 if (!semihosting->is_active) {
1583 command_print(CMD_CTX, "semihosting not yet enabled for current target");
1584 return ERROR_FAIL;
1587 if (CMD_ARGC > 0)
1588 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
1590 command_print(CMD_CTX, "semihosting resumable exit is %s",
1591 semihosting->has_resumable_exit
1592 ? "enabled" : "disabled");
1594 return ERROR_OK;