semihosting: add custom user command handler
[fw/openocd] / src / target / semihosting_common.c
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  ***************************************************************************/
27
28 /**
29  * @file
30  * Common ARM semihosting support.
31  *
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.
36  *
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.
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include "target.h"
48 #include "target_type.h"
49 #include "semihosting_common.h"
50
51 #include <helper/binarybuffer.h>
52 #include <helper/log.h>
53 #include <sys/stat.h>
54
55 /**
56  * It is not possible to use O_... flags defined in sys/stat.h because they
57  * are not guaranteed to match the values defined by the GDB Remote Protocol.
58  * See https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags
59  */
60 enum {
61         TARGET_O_RDONLY = 0x000,
62         TARGET_O_WRONLY = 0x001,
63         TARGET_O_RDWR   = 0x002,
64         TARGET_O_APPEND = 0x008,
65         TARGET_O_CREAT  = 0x200,
66         TARGET_O_TRUNC  = 0x400,
67         /* O_EXCL=0x800 is not required in this implementation. */
68 };
69
70 /* GDB remote protocol does not differentiate between text and binary open modes. */
71 static const int open_gdb_modeflags[12] = {
72         TARGET_O_RDONLY,
73         TARGET_O_RDONLY,
74         TARGET_O_RDWR,
75         TARGET_O_RDWR,
76         TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,
77         TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,
78         TARGET_O_RDWR   | TARGET_O_CREAT | TARGET_O_TRUNC,
79         TARGET_O_RDWR   | TARGET_O_CREAT | TARGET_O_TRUNC,
80         TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,
81         TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,
82         TARGET_O_RDWR   | TARGET_O_CREAT | TARGET_O_APPEND,
83         TARGET_O_RDWR   | TARGET_O_CREAT | TARGET_O_APPEND
84 };
85
86 static const int open_host_modeflags[12] = {
87         O_RDONLY,
88         O_RDONLY | O_BINARY,
89         O_RDWR,
90         O_RDWR   | O_BINARY,
91         O_WRONLY | O_CREAT | O_TRUNC,
92         O_WRONLY | O_CREAT | O_TRUNC  | O_BINARY,
93         O_RDWR   | O_CREAT | O_TRUNC,
94         O_RDWR   | O_CREAT | O_TRUNC  | O_BINARY,
95         O_WRONLY | O_CREAT | O_APPEND,
96         O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
97         O_RDWR   | O_CREAT | O_APPEND,
98         O_RDWR   | O_CREAT | O_APPEND | O_BINARY
99 };
100
101 static int semihosting_common_fileio_info(struct target *target,
102         struct gdb_fileio_info *fileio_info);
103 static int semihosting_common_fileio_end(struct target *target, int result,
104         int fileio_errno, bool ctrl_c);
105
106 /* Attempts to include gdb_server.h failed. */
107 extern int gdb_actual_connections;
108
109 /**
110  * Initialize common semihosting support.
111  *
112  * @param target Pointer to the target to initialize.
113  * @param setup
114  * @param post_result
115  * @return An error status if there is a problem during initialization.
116  */
117 int semihosting_common_init(struct target *target, void *setup,
118         void *post_result)
119 {
120         LOG_DEBUG(" ");
121
122         target->fileio_info = malloc(sizeof(*target->fileio_info));
123         if (!target->fileio_info) {
124                 LOG_ERROR("out of memory");
125                 return ERROR_FAIL;
126         }
127         memset(target->fileio_info, 0, sizeof(*target->fileio_info));
128
129         struct semihosting *semihosting;
130         semihosting = malloc(sizeof(*target->semihosting));
131         if (!semihosting) {
132                 LOG_ERROR("out of memory");
133                 return ERROR_FAIL;
134         }
135
136         semihosting->is_active = false;
137         semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
138         semihosting->tcp_connection = NULL;
139         semihosting->stdin_fd = -1;
140         semihosting->stdout_fd = -1;
141         semihosting->stderr_fd = -1;
142         semihosting->is_fileio = false;
143         semihosting->hit_fileio = false;
144         semihosting->is_resumable = false;
145         semihosting->has_resumable_exit = false;
146         semihosting->word_size_bytes = 0;
147         semihosting->op = -1;
148         semihosting->param = 0;
149         semihosting->result = -1;
150         semihosting->sys_errno = -1;
151         semihosting->cmdline = NULL;
152         semihosting->basedir = NULL;
153
154         /* If possible, update it in setup(). */
155         semihosting->setup_time = clock();
156
157         semihosting->setup = setup;
158         semihosting->post_result = post_result;
159         semihosting->user_command_extension = NULL;
160
161         target->semihosting = semihosting;
162
163         target->type->get_gdb_fileio_info = semihosting_common_fileio_info;
164         target->type->gdb_fileio_end = semihosting_common_fileio_end;
165
166         return ERROR_OK;
167 }
168
169 struct semihosting_tcp_service {
170         struct semihosting *semihosting;
171         char *name;
172         int error;
173 };
174
175 static bool semihosting_is_redirected(struct semihosting *semihosting, int fd)
176 {
177         if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_NONE)
178                 return false;
179
180         bool is_read_op = false;
181
182         switch (semihosting->op) {
183         /* check debug semihosting operations: READC, WRITEC and WRITE0 */
184         case SEMIHOSTING_SYS_READC:
185                 is_read_op = true;
186                 /* fall through */
187         case SEMIHOSTING_SYS_WRITEC:
188         case SEMIHOSTING_SYS_WRITE0:
189                 /* debug operations are redirected when CFG is either DEBUG or ALL */
190                 if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_STDIO)
191                         return false;
192                 break;
193
194         /* check stdio semihosting operations: READ and WRITE */
195         case SEMIHOSTING_SYS_READ:
196                 is_read_op = true;
197                 /* fall through */
198         case SEMIHOSTING_SYS_WRITE:
199                 /* stdio operations are redirected when CFG is either STDIO or ALL */
200                 if (semihosting->redirect_cfg == SEMIHOSTING_REDIRECT_CFG_DEBUG)
201                         return false;
202                 break;
203
204         default:
205                 return false;
206         }
207
208         if (is_read_op)
209                 return fd == semihosting->stdin_fd;
210
211         /* write operation */
212         return fd == semihosting->stdout_fd || fd == semihosting->stderr_fd;
213 }
214
215 static ssize_t semihosting_redirect_write(struct semihosting *semihosting, void *buf, int size)
216 {
217         if (!semihosting->tcp_connection) {
218                 LOG_ERROR("No connected TCP client for semihosting");
219                 semihosting->sys_errno = EBADF; /* Bad file number */
220                 return -1;
221         }
222
223         struct semihosting_tcp_service *service = semihosting->tcp_connection->service->priv;
224
225         int retval = connection_write(semihosting->tcp_connection, buf, size);
226
227         if (retval < 0)
228                 log_socket_error(service->name);
229
230         return retval;
231 }
232
233 static ssize_t semihosting_write(struct semihosting *semihosting, int fd, void *buf, int size)
234 {
235         if (semihosting_is_redirected(semihosting, fd))
236                 return semihosting_redirect_write(semihosting, buf, size);
237
238         /* default write */
239         return write(fd, buf, size);
240 }
241
242 static ssize_t semihosting_redirect_read(struct semihosting *semihosting, void *buf, int size)
243 {
244         if (!semihosting->tcp_connection) {
245                 LOG_ERROR("No connected TCP client for semihosting");
246                 semihosting->sys_errno = EBADF; /* Bad file number */
247                 return -1;
248         }
249
250         struct semihosting_tcp_service *service = semihosting->tcp_connection->service->priv;
251
252         service->error = ERROR_OK;
253         semihosting->tcp_connection->input_pending = true;
254
255         int retval = connection_read(semihosting->tcp_connection, buf, size);
256
257         if (retval <= 0)
258                 service->error = ERROR_SERVER_REMOTE_CLOSED;
259
260         if (retval < 0)
261                 log_socket_error(service->name);
262
263         semihosting->tcp_connection->input_pending = false;
264
265         return retval;
266 }
267
268 static inline int semihosting_putchar(struct semihosting *semihosting, int fd, int c)
269 {
270         if (semihosting_is_redirected(semihosting, fd))
271                 return semihosting_redirect_write(semihosting, &c, 1);
272
273         /* default putchar */
274         return putchar(c);
275 }
276
277 static inline ssize_t semihosting_read(struct semihosting *semihosting, int fd, void *buf, int size)
278 {
279         if (semihosting_is_redirected(semihosting, fd))
280                 return semihosting_redirect_read(semihosting, buf, size);
281
282         /* default read */
283         ssize_t result = read(fd, buf, size);
284         semihosting->sys_errno = errno;
285
286         return result;
287 }
288
289 static inline int semihosting_getchar(struct semihosting *semihosting, int fd)
290 {
291         if (semihosting_is_redirected(semihosting, fd)) {
292                 unsigned char c;
293
294                 if (semihosting_redirect_read(semihosting, &c, 1) > 0)
295                         return c;
296
297                 return EOF;
298         }
299
300         /* default getchar */
301         return getchar();
302 }
303
304 /**
305  * User operation parameter string storage buffer. Contains valid data when the
306  * TARGET_EVENT_SEMIHOSTING_USER_CMD_xxxxx event callbacks are running.
307  */
308 static char *semihosting_user_op_params;
309
310 /**
311  * Portable implementation of ARM semihosting calls.
312  * Performs the currently pending semihosting operation
313  * encoded in target->semihosting.
314  */
315 int semihosting_common(struct target *target)
316 {
317         struct semihosting *semihosting = target->semihosting;
318         if (!semihosting) {
319                 /* Silently ignore if the semihosting field was not set. */
320                 return ERROR_OK;
321         }
322
323         struct gdb_fileio_info *fileio_info = target->fileio_info;
324
325         /*
326          * By default return an error.
327          * The actual result must be set by each function
328          */
329         semihosting->result = -1;
330
331         /* Most operations are resumable, except the two exit calls. */
332         semihosting->is_resumable = true;
333
334         int retval;
335
336         /* Enough space to hold 4 long words. */
337         uint8_t fields[4*8];
338
339         LOG_DEBUG("op=0x%x, param=0x%" PRIx64, semihosting->op,
340                 semihosting->param);
341
342         switch (semihosting->op) {
343
344                 case SEMIHOSTING_SYS_CLOCK:     /* 0x10 */
345                         /*
346                          * Returns the number of centiseconds (hundredths of a second)
347                          * since the execution started.
348                          *
349                          * Values returned can be of limited use for some benchmarking
350                          * purposes because of communication overhead or other
351                          * agent-specific factors. For example, with a debug hardware
352                          * unit the request is passed back to the host for execution.
353                          * This can lead to unpredictable delays in transmission and
354                          * process scheduling.
355                          *
356                          * Use this function to calculate time intervals, by calculating
357                          * differences between intervals with and without the code
358                          * sequence to be timed.
359                          *
360                          * Entry
361                          * The PARAMETER REGISTER must contain 0. There are no other
362                          * parameters.
363                          *
364                          * Return
365                          * On exit, the RETURN REGISTER contains:
366                          * - The number of centiseconds since some arbitrary start
367                          * point, if the call is successful.
368                          * - â€“1 if the call is not successful. For example, because
369                          * of a communications error.
370                          */
371                 {
372                         clock_t delta = clock() - semihosting->setup_time;
373
374                         semihosting->result = delta / (CLOCKS_PER_SEC / 100);
375                 }
376                 break;
377
378                 case SEMIHOSTING_SYS_CLOSE:     /* 0x02 */
379                         /*
380                          * Closes a file on the host system. The handle must reference
381                          * a file that was opened with SYS_OPEN.
382                          *
383                          * Entry
384                          * On entry, the PARAMETER REGISTER contains a pointer to a
385                          * one-field argument block:
386                          * - field 1 Contains a handle for an open file.
387                          *
388                          * Return
389                          * On exit, the RETURN REGISTER contains:
390                          * - 0 if the call is successful
391                          * - â€“1 if the call is not successful.
392                          */
393                         retval = semihosting_read_fields(target, 1, fields);
394                         if (retval != ERROR_OK)
395                                 return retval;
396                         else {
397                                 int fd = semihosting_get_field(target, 0, fields);
398                                 /* Do not allow to close OpenOCD's own standard streams */
399                                 if (fd == 0 || fd == 1 || fd == 2) {
400                                         LOG_DEBUG("ignoring semihosting attempt to close %s",
401                                                         (fd == 0) ? "stdin" :
402                                                         (fd == 1) ? "stdout" : "stderr");
403                                         /* Just pretend success */
404                                         if (semihosting->is_fileio) {
405                                                 semihosting->result = 0;
406                                         } else {
407                                                 semihosting->result = 0;
408                                                 semihosting->sys_errno = 0;
409                                         }
410                                         break;
411                                 }
412                                 /* Close the descriptor */
413                                 if (semihosting->is_fileio) {
414                                         semihosting->hit_fileio = true;
415                                         fileio_info->identifier = "close";
416                                         fileio_info->param_1 = fd;
417                                 } else {
418                                         semihosting->result = close(fd);
419                                         semihosting->sys_errno = errno;
420                                         LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result);
421                                 }
422                         }
423                         break;
424
425                 case SEMIHOSTING_SYS_ERRNO:     /* 0x13 */
426                         /*
427                          * Returns the value of the C library errno variable that is
428                          * associated with the semihosting implementation. The errno
429                          * variable can be set by a number of C library semihosted
430                          * functions, including:
431                          * - SYS_REMOVE
432                          * - SYS_OPEN
433                          * - SYS_CLOSE
434                          * - SYS_READ
435                          * - SYS_WRITE
436                          * - SYS_SEEK.
437                          *
438                          * Whether errno is set or not, and to what value, is entirely
439                          * host-specific, except where the ISO C standard defines the
440                          * behavior.
441                          *
442                          * Entry
443                          * There are no parameters. The PARAMETER REGISTER must be 0.
444                          *
445                          * Return
446                          * On exit, the RETURN REGISTER contains the value of the C
447                          * library errno variable.
448                          */
449                         semihosting->result = semihosting->sys_errno;
450                         break;
451
452                 case SEMIHOSTING_SYS_EXIT:      /* 0x18 */
453                         /*
454                          * Note: SYS_EXIT was called angel_SWIreason_ReportException in
455                          * previous versions of the documentation.
456                          *
457                          * An application calls this operation to report an exception
458                          * to the debugger directly. The most common use is to report
459                          * that execution has completed, using ADP_Stopped_ApplicationExit.
460                          *
461                          * Note: This semihosting operation provides no means for 32-bit
462                          * callers to indicate an application exit with a specified exit
463                          * code. Semihosting callers may prefer to check for the presence
464                          * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
465                          * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
466                          * is available.
467                          *
468                          * Entry (32-bit)
469                          * On entry, the PARAMETER register is set to a reason code
470                          * describing the cause of the trap. Not all semihosting client
471                          * implementations will necessarily trap every corresponding
472                          * event. Important reason codes are:
473                          *
474                          * - ADP_Stopped_ApplicationExit 0x20026
475                          * - ADP_Stopped_RunTimeErrorUnknown 0x20023
476                          *
477                          * Entry (64-bit)
478                          * On entry, the PARAMETER REGISTER contains a pointer to a
479                          * two-field argument block:
480                          * - field 1 The exception type, which is one of the set of
481                          * reason codes in the above tables.
482                          * - field 2 A subcode, whose meaning depends on the reason
483                          * code in field 1.
484                          * In particular, if field 1 is ADP_Stopped_ApplicationExit
485                          * then field 2 is an exit status code, as passed to the C
486                          * standard library exit() function. A simulator receiving
487                          * this request must notify a connected debugger, if present,
488                          * and then exit with the specified status.
489                          *
490                          * Return
491                          * No return is expected from these calls. However, it is
492                          * possible for the debugger to request that the application
493                          * continues by performing an RDI_Execute request or equivalent.
494                          * In this case, execution continues with the registers as they
495                          * were on entry to the operation, or as subsequently modified
496                          * by the debugger.
497                          */
498                         if (semihosting->word_size_bytes == 8) {
499                                 retval = semihosting_read_fields(target, 2, fields);
500                                 if (retval != ERROR_OK)
501                                         return retval;
502                                 else {
503                                         int type = semihosting_get_field(target, 0, fields);
504                                         int code = semihosting_get_field(target, 1, fields);
505
506                                         if (type == ADP_STOPPED_APPLICATION_EXIT) {
507                                                 if (!gdb_actual_connections)
508                                                         exit(code);
509                                                 else {
510                                                         fprintf(stderr,
511                                                                 "semihosting: *** application exited with %d ***\n",
512                                                                 code);
513                                                 }
514                                         } else {
515                                                 fprintf(stderr,
516                                                         "semihosting: application exception %#x\n",
517                                                         type);
518                                         }
519                                 }
520                         } else {
521                                 if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
522                                         if (!gdb_actual_connections)
523                                                 exit(0);
524                                         else {
525                                                 fprintf(stderr,
526                                                         "semihosting: *** application exited normally ***\n");
527                                         }
528                                 } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
529                                         /* Chosen more or less arbitrarily to have a nicer message,
530                                          * otherwise all other return the same exit code 1. */
531                                         if (!gdb_actual_connections)
532                                                 exit(1);
533                                         else {
534                                                 fprintf(stderr,
535                                                         "semihosting: *** application exited with error ***\n");
536                                         }
537                                 } else {
538                                         if (!gdb_actual_connections)
539                                                 exit(1);
540                                         else {
541                                                 fprintf(stderr,
542                                                         "semihosting: application exception %#x\n",
543                                                         (unsigned) semihosting->param);
544                                         }
545                                 }
546                         }
547                         if (!semihosting->has_resumable_exit) {
548                                 semihosting->is_resumable = false;
549                                 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
550                         }
551                         break;
552
553                 case SEMIHOSTING_SYS_EXIT_EXTENDED:     /* 0x20 */
554                         /*
555                          * This operation is only supported if the semihosting extension
556                          * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
557                          * reported using feature byte 0, bit 0. If this extension is
558                          * supported, then the implementation provides a means to
559                          * report a normal exit with a nonzero exit status in both 32-bit
560                          * and 64-bit semihosting APIs.
561                          *
562                          * The implementation must provide the semihosting call
563                          * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
564                          *
565                          * SYS_EXIT_EXTENDED is used by an application to report an
566                          * exception or exit to the debugger directly. The most common
567                          * use is to report that execution has completed, using
568                          * ADP_Stopped_ApplicationExit.
569                          *
570                          * Entry
571                          * On entry, the PARAMETER REGISTER contains a pointer to a
572                          * two-field argument block:
573                          * - field 1 The exception type, which should be one of the set
574                          * of reason codes that are documented for the SYS_EXIT
575                          * (0x18) call. For example, ADP_Stopped_ApplicationExit.
576                          * - field 2 A subcode, whose meaning depends on the reason
577                          * code in field 1. In particular, if field 1 is
578                          * ADP_Stopped_ApplicationExit then field 2 is an exit status
579                          * code, as passed to the C standard library exit() function.
580                          * A simulator receiving this request must notify a connected
581                          * debugger, if present, and then exit with the specified status.
582                          *
583                          * Return
584                          * No return is expected from these calls.
585                          *
586                          * For the A64 API, this call is identical to the behavior of
587                          * the mandatory SYS_EXIT (0x18) call. If this extension is
588                          * supported, then both calls must be implemented.
589                          */
590                         retval = semihosting_read_fields(target, 2, fields);
591                         if (retval != ERROR_OK)
592                                 return retval;
593                         else {
594                                 int type = semihosting_get_field(target, 0, fields);
595                                 int code = semihosting_get_field(target, 1, fields);
596
597                                 if (type == ADP_STOPPED_APPLICATION_EXIT) {
598                                         if (!gdb_actual_connections)
599                                                 exit(code);
600                                         else {
601                                                 fprintf(stderr,
602                                                         "semihosting: *** application exited with %d ***\n",
603                                                         code);
604                                         }
605                                 } else {
606                                         fprintf(stderr, "semihosting: exception %#x\n",
607                                                 type);
608                                 }
609                         }
610                         if (!semihosting->has_resumable_exit) {
611                                 semihosting->is_resumable = false;
612                                 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
613                         }
614                         break;
615
616                 case SEMIHOSTING_SYS_FLEN:      /* 0x0C */
617                         /*
618                          * Returns the length of a specified file.
619                          *
620                          * Entry
621                          * On entry, the PARAMETER REGISTER contains a pointer to a
622                          * one-field argument block:
623                          * - field 1 A handle for a previously opened, seekable file
624                          * object.
625                          *
626                          * Return
627                          * On exit, the RETURN REGISTER contains:
628                          * - The current length of the file object, if the call is
629                          * successful.
630                          * - â€“1 if an error occurs.
631                          */
632                         if (semihosting->is_fileio) {
633                                 semihosting->result = -1;
634                                 semihosting->sys_errno = EINVAL;
635                         }
636                         retval = semihosting_read_fields(target, 1, fields);
637                         if (retval != ERROR_OK)
638                                 return retval;
639                         else {
640                                 int fd = semihosting_get_field(target, 0, fields);
641                                 struct stat buf;
642                                 semihosting->result = fstat(fd, &buf);
643                                 if (semihosting->result == -1) {
644                                         semihosting->sys_errno = errno;
645                                         LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
646                                         break;
647                                 }
648                                 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
649                                 semihosting->result = buf.st_size;
650                         }
651                         break;
652
653                 case SEMIHOSTING_SYS_GET_CMDLINE:       /* 0x15 */
654                         /*
655                          * Returns the command line that is used for the call to the
656                          * executable, that is, argc and argv.
657                          *
658                          * Entry
659                          * On entry, the PARAMETER REGISTER points to a two-field data
660                          * block to be used for returning the command string and its length:
661                          * - field 1 A pointer to a buffer of at least the size that is
662                          * specified in field 2.
663                          * - field 2 The length of the buffer in bytes.
664                          *
665                          * Return
666                          * On exit:
667                          * If the call is successful, then the RETURN REGISTER contains 0,
668                          * the PARAMETER REGISTER is unchanged, and the data block is
669                          * updated as follows:
670                          * - field 1 A pointer to a null-terminated string of the command
671                          * line.
672                          * - field 2 The length of the string in bytes.
673                          * If the call is not successful, then the RETURN REGISTER
674                          * contains -1.
675                          *
676                          * Note: The semihosting implementation might impose limits on
677                          * the maximum length of the string that can be transferred.
678                          * However, the implementation must be able to support a
679                          * command-line length of at least 80 bytes.
680                          */
681                         retval = semihosting_read_fields(target, 2, fields);
682                         if (retval != ERROR_OK)
683                                 return retval;
684                         else {
685                                 uint64_t addr = semihosting_get_field(target, 0, fields);
686                                 size_t size = semihosting_get_field(target, 1, fields);
687
688                                 char *arg = semihosting->cmdline ?
689                                         semihosting->cmdline : "";
690                                 uint32_t len = strlen(arg) + 1;
691                                 if (len > size)
692                                         semihosting->result = -1;
693                                 else {
694                                         semihosting_set_field(target, len, 1, fields);
695                                         retval = target_write_buffer(target, addr, len,
696                                                         (uint8_t *)arg);
697                                         if (retval != ERROR_OK)
698                                                 return retval;
699                                         semihosting->result = 0;
700
701                                         retval = semihosting_write_fields(target, 2, fields);
702                                         if (retval != ERROR_OK)
703                                                 return retval;
704                                 }
705                                 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg,
706                                         (int)semihosting->result);
707                         }
708                         break;
709
710                 case SEMIHOSTING_SYS_HEAPINFO:  /* 0x16 */
711                         /*
712                          * Returns the system stack and heap parameters.
713                          *
714                          * Entry
715                          * On entry, the PARAMETER REGISTER contains the address of a
716                          * pointer to a four-field data block. The contents of the data
717                          * block are filled by the function. The following C-like
718                          * pseudocode describes the layout of the block:
719                          * struct block {
720                          *   void* heap_base;
721                          *   void* heap_limit;
722                          *   void* stack_base;
723                          *   void* stack_limit;
724                          * };
725                          *
726                          * Return
727                          * On exit, the PARAMETER REGISTER is unchanged and the data
728                          * block has been updated.
729                          */
730                         retval = semihosting_read_fields(target, 1, fields);
731                         if (retval != ERROR_OK)
732                                 return retval;
733                         else {
734                                 uint64_t addr = semihosting_get_field(target, 0, fields);
735                                 /* tell the remote we have no idea */
736                                 memset(fields, 0, 4 * semihosting->word_size_bytes);
737                                 retval = target_write_memory(target, addr, 4,
738                                                 semihosting->word_size_bytes,
739                                                 fields);
740                                 if (retval != ERROR_OK)
741                                         return retval;
742                                 semihosting->result = 0;
743                         }
744                         break;
745
746                 case SEMIHOSTING_SYS_ISERROR:   /* 0x08 */
747                         /*
748                          * Determines whether the return code from another semihosting
749                          * call is an error status or not.
750                          *
751                          * This call is passed a parameter block containing the error
752                          * code to examine.
753                          *
754                          * Entry
755                          * On entry, the PARAMETER REGISTER contains a pointer to a
756                          * one-field data block:
757                          * - field 1 The required status word to check.
758                          *
759                          * Return
760                          * On exit, the RETURN REGISTER contains:
761                          * - 0 if the status field is not an error indication
762                          * - A nonzero value if the status field is an error indication.
763                          */
764                         retval = semihosting_read_fields(target, 1, fields);
765                         if (retval != ERROR_OK)
766                                 return retval;
767
768                         uint64_t code = semihosting_get_field(target, 0, fields);
769                         semihosting->result = (code != 0);
770                         break;
771
772                 case SEMIHOSTING_SYS_ISTTY:     /* 0x09 */
773                         /*
774                          * Checks whether a file is connected to an interactive device.
775                          *
776                          * Entry
777                          * On entry, the PARAMETER REGISTER contains a pointer to a
778                          * one-field argument block:
779                          * field 1 A handle for a previously opened file object.
780                          *
781                          * Return
782                          * On exit, the RETURN REGISTER contains:
783                          * - 1 if the handle identifies an interactive device.
784                          * - 0 if the handle identifies a file.
785                          * - A value other than 1 or 0 if an error occurs.
786                          */
787                         if (semihosting->is_fileio) {
788                                 semihosting->hit_fileio = true;
789                                 fileio_info->identifier = "isatty";
790                                 fileio_info->param_1 = semihosting->param;
791                         } else {
792                                 retval = semihosting_read_fields(target, 1, fields);
793                                 if (retval != ERROR_OK)
794                                         return retval;
795                                 int fd = semihosting_get_field(target, 0, fields);
796                                 semihosting->result = isatty(fd);
797                                 semihosting->sys_errno = errno;
798                                 LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result);
799                         }
800                         break;
801
802                 case SEMIHOSTING_SYS_OPEN:      /* 0x01 */
803                         /*
804                          * Opens a file on the host system.
805                          *
806                          * The file path is specified either as relative to the current
807                          * directory of the host process, or absolute, using the path
808                          * conventions of the host operating system.
809                          *
810                          * Semihosting implementations must support opening the special
811                          * path name :semihosting-features as part of the semihosting
812                          * extensions reporting mechanism.
813                          *
814                          * ARM targets interpret the special path name :tt as meaning
815                          * the console input stream, for an open-read or the console
816                          * output stream, for an open-write. Opening these streams is
817                          * performed as part of the standard startup code for those
818                          * applications that reference the C stdio streams. The
819                          * semihosting extension SH_EXT_STDOUT_STDERR allows the
820                          * semihosting caller to open separate output streams
821                          * corresponding to stdout and stderr. This extension is
822                          * reported using feature byte 0, bit 1. Use SYS_OPEN with
823                          * the special path name :semihosting-features to access the
824                          * feature bits.
825                          *
826                          * If this extension is supported, the implementation must
827                          * support the following additional semantics to SYS_OPEN:
828                          * - If the special path name :tt is opened with an fopen
829                          * mode requesting write access (w, wb, w+, or w+b), then
830                          * this is a request to open stdout.
831                          * - If the special path name :tt is opened with a mode
832                          * requesting append access (a, ab, a+, or a+b), then this is
833                          * a request to open stderr.
834                          *
835                          * Entry
836                          * On entry, the PARAMETER REGISTER contains a pointer to a
837                          * three-field argument block:
838                          * - field 1 A pointer to a null-terminated string containing
839                          * a file or device name.
840                          * - field 2 An integer that specifies the file opening mode.
841                          * - field 3 An integer that gives the length of the string
842                          * pointed to by field 1.
843                          *
844                          * The length does not include the terminating null character
845                          * that must be present.
846                          *
847                          * Return
848                          * On exit, the RETURN REGISTER contains:
849                          * - A nonzero handle if the call is successful.
850                          * - â€“1 if the call is not successful.
851                          */
852                         retval = semihosting_read_fields(target, 3, fields);
853                         if (retval != ERROR_OK)
854                                 return retval;
855                         else {
856                                 uint64_t addr = semihosting_get_field(target, 0, fields);
857                                 uint32_t mode = semihosting_get_field(target, 1, fields);
858                                 size_t len = semihosting_get_field(target, 2, fields);
859
860                                 if (mode > 11) {
861                                         semihosting->result = -1;
862                                         semihosting->sys_errno = EINVAL;
863                                         break;
864                                 }
865                                 size_t basedir_len = semihosting->basedir ? strlen(semihosting->basedir) : 0;
866                                 uint8_t *fn = malloc(basedir_len + len + 2);
867                                 if (!fn) {
868                                         semihosting->result = -1;
869                                         semihosting->sys_errno = ENOMEM;
870                                 } else {
871                                         if (basedir_len > 0) {
872                                                 strcpy((char *)fn, semihosting->basedir);
873                                                 if (fn[basedir_len - 1] != '/')
874                                                         fn[basedir_len++] = '/';
875                                         }
876                                         retval = target_read_memory(target, addr, 1, len, fn + basedir_len);
877                                         if (retval != ERROR_OK) {
878                                                 free(fn);
879                                                 return retval;
880                                         }
881                                         fn[basedir_len + len] = 0;
882                                         /* TODO: implement the :semihosting-features special file.
883                                          * */
884                                         if (semihosting->is_fileio) {
885                                                 if (strcmp((char *)fn, ":semihosting-features") == 0) {
886                                                         semihosting->result = -1;
887                                                         semihosting->sys_errno = EINVAL;
888                                                 } else if (strcmp((char *)fn, ":tt") == 0) {
889                                                         if (mode == 0)
890                                                                 semihosting->result = 0;
891                                                         else if (mode == 4)
892                                                                 semihosting->result = 1;
893                                                         else if (mode == 8)
894                                                                 semihosting->result = 2;
895                                                         else
896                                                                 semihosting->result = -1;
897                                                 } else {
898                                                         semihosting->hit_fileio = true;
899                                                         fileio_info->identifier = "open";
900                                                         fileio_info->param_1 = addr;
901                                                         fileio_info->param_2 = len;
902                                                         fileio_info->param_3 = open_gdb_modeflags[mode];
903                                                         fileio_info->param_4 = 0644;
904                                                 }
905                                         } else {
906                                                 if (strcmp((char *)fn, ":tt") == 0) {
907                                                         /* Mode is:
908                                                          * - 0-3 ("r") for stdin,
909                                                          * - 4-7 ("w") for stdout,
910                                                          * - 8-11 ("a") for stderr */
911                                                         if (mode < 4) {
912                                                                 int fd = dup(STDIN_FILENO);
913                                                                 semihosting->result = fd;
914                                                                 semihosting->stdin_fd = fd;
915                                                                 semihosting->sys_errno = errno;
916                                                                 LOG_DEBUG("dup(STDIN)=%d",
917                                                                         (int)semihosting->result);
918                                                         } else if (mode < 8) {
919                                                                 int fd = dup(STDOUT_FILENO);
920                                                                 semihosting->result = fd;
921                                                                 semihosting->stdout_fd = fd;
922                                                                 semihosting->sys_errno = errno;
923                                                                 LOG_DEBUG("dup(STDOUT)=%d",
924                                                                         (int)semihosting->result);
925                                                         } else {
926                                                                 int fd = dup(STDERR_FILENO);
927                                                                 semihosting->result = fd;
928                                                                 semihosting->stderr_fd = fd;
929                                                                 semihosting->sys_errno = errno;
930                                                                 LOG_DEBUG("dup(STDERR)=%d",
931                                                                         (int)semihosting->result);
932                                                         }
933                                                 } else {
934                                                         /* cygwin requires the permission setting
935                                                          * otherwise it will fail to reopen a previously
936                                                          * written file */
937                                                         semihosting->result = open((char *)fn,
938                                                                         open_host_modeflags[mode],
939                                                                         0644);
940                                                         semihosting->sys_errno = errno;
941                                                         LOG_DEBUG("open('%s')=%d", fn,
942                                                                 (int)semihosting->result);
943                                                 }
944                                         }
945                                         free(fn);
946                                 }
947                         }
948                         break;
949
950                 case SEMIHOSTING_SYS_READ:      /* 0x06 */
951                         /*
952                          * Reads the contents of a file into a buffer. The file position
953                          * is specified either:
954                          * - Explicitly by a SYS_SEEK.
955                          * - Implicitly one byte beyond the previous SYS_READ or
956                          * SYS_WRITE request.
957                          *
958                          * The file position is at the start of the file when it is
959                          * opened, and is lost when the file is closed. Perform the
960                          * file operation as a single action whenever possible. For
961                          * example, do not split a read of 16KB into four 4KB chunks
962                          * unless there is no alternative.
963                          *
964                          * Entry
965                          * On entry, the PARAMETER REGISTER contains a pointer to a
966                          * three-field data block:
967                          * - field 1 Contains a handle for a file previously opened
968                          * with SYS_OPEN.
969                          * - field 2 Points to a buffer.
970                          * - field 3 Contains the number of bytes to read to the buffer
971                          * from the file.
972                          *
973                          * Return
974                          * On exit, the RETURN REGISTER contains the number of bytes not
975                          * filled in the buffer (buffer_length - bytes_read) as follows:
976                          * - If the RETURN REGISTER is 0, the entire buffer was
977                          * successfully filled.
978                          * - If the RETURN REGISTER is the same as field 3, no bytes
979                          * were read (EOF can be assumed).
980                          * - If the RETURN REGISTER contains a value smaller than
981                          * field 3, the read succeeded but the buffer was only partly
982                          * filled. For interactive devices, this is the most common
983                          * return value.
984                          */
985                         retval = semihosting_read_fields(target, 3, fields);
986                         if (retval != ERROR_OK)
987                                 return retval;
988                         else {
989                                 int fd = semihosting_get_field(target, 0, fields);
990                                 uint64_t addr = semihosting_get_field(target, 1, fields);
991                                 size_t len = semihosting_get_field(target, 2, fields);
992                                 if (semihosting->is_fileio) {
993                                         semihosting->hit_fileio = true;
994                                         fileio_info->identifier = "read";
995                                         fileio_info->param_1 = fd;
996                                         fileio_info->param_2 = addr;
997                                         fileio_info->param_3 = len;
998                                 } else {
999                                         uint8_t *buf = malloc(len);
1000                                         if (!buf) {
1001                                                 semihosting->result = -1;
1002                                                 semihosting->sys_errno = ENOMEM;
1003                                         } else {
1004                                                 semihosting->result = semihosting_read(semihosting, fd, buf, len);
1005                                                 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
1006                                                         fd,
1007                                                         addr,
1008                                                         len,
1009                                                         (int)semihosting->result);
1010                                                 if (semihosting->result >= 0) {
1011                                                         retval = target_write_buffer(target, addr,
1012                                                                         semihosting->result,
1013                                                                         buf);
1014                                                         if (retval != ERROR_OK) {
1015                                                                 free(buf);
1016                                                                 return retval;
1017                                                         }
1018                                                         /* the number of bytes NOT filled in */
1019                                                         semihosting->result = len -
1020                                                                 semihosting->result;
1021                                                 }
1022                                                 free(buf);
1023                                         }
1024                                 }
1025                         }
1026                         break;
1027
1028                 case SEMIHOSTING_SYS_READC:     /* 0x07 */
1029                         /*
1030                          * Reads a byte from the console.
1031                          *
1032                          * Entry
1033                          * The PARAMETER REGISTER must contain 0. There are no other
1034                          * parameters or values possible.
1035                          *
1036                          * Return
1037                          * On exit, the RETURN REGISTER contains the byte read from
1038                          * the console.
1039                          */
1040                         if (semihosting->is_fileio) {
1041                                 LOG_ERROR("SYS_READC not supported by semihosting fileio");
1042                                 return ERROR_FAIL;
1043                         }
1044                         semihosting->result = semihosting_getchar(semihosting, semihosting->stdin_fd);
1045                         LOG_DEBUG("getchar()=%d", (int)semihosting->result);
1046                         break;
1047
1048                 case SEMIHOSTING_SYS_REMOVE:    /* 0x0E */
1049                         /*
1050                          * Deletes a specified file on the host filing system.
1051                          *
1052                          * Entry
1053                          * On entry, the PARAMETER REGISTER contains a pointer to a
1054                          * two-field argument block:
1055                          * - field 1 Points to a null-terminated string that gives the
1056                          * path name of the file to be deleted.
1057                          * - field 2 The length of the string.
1058                          *
1059                          * Return
1060                          * On exit, the RETURN REGISTER contains:
1061                          * - 0 if the delete is successful
1062                          * - A nonzero, host-specific error code if the delete fails.
1063                          */
1064                         retval = semihosting_read_fields(target, 2, fields);
1065                         if (retval != ERROR_OK)
1066                                 return retval;
1067                         else {
1068                                 uint64_t addr = semihosting_get_field(target, 0, fields);
1069                                 size_t len = semihosting_get_field(target, 1, fields);
1070                                 if (semihosting->is_fileio) {
1071                                         semihosting->hit_fileio = true;
1072                                         fileio_info->identifier = "unlink";
1073                                         fileio_info->param_1 = addr;
1074                                         fileio_info->param_2 = len;
1075                                 } else {
1076                                         uint8_t *fn = malloc(len+1);
1077                                         if (!fn) {
1078                                                 semihosting->result = -1;
1079                                                 semihosting->sys_errno = ENOMEM;
1080                                         } else {
1081                                                 retval =
1082                                                         target_read_memory(target, addr, 1, len,
1083                                                                 fn);
1084                                                 if (retval != ERROR_OK) {
1085                                                         free(fn);
1086                                                         return retval;
1087                                                 }
1088                                                 fn[len] = 0;
1089                                                 semihosting->result = remove((char *)fn);
1090                                                 semihosting->sys_errno = errno;
1091                                                 LOG_DEBUG("remove('%s')=%d", fn,
1092                                                         (int)semihosting->result);
1093
1094                                                 free(fn);
1095                                         }
1096                                 }
1097                         }
1098                         break;
1099
1100                 case SEMIHOSTING_SYS_RENAME:    /* 0x0F */
1101                         /*
1102                          * Renames a specified file.
1103                          *
1104                          * Entry
1105                          * On entry, the PARAMETER REGISTER contains a pointer to a
1106                          * four-field data block:
1107                          * - field 1 A pointer to the name of the old file.
1108                          * - field 2 The length of the old filename.
1109                          * - field 3 A pointer to the new filename.
1110                          * - field 4 The length of the new filename. Both strings are
1111                          * null-terminated.
1112                          *
1113                          * Return
1114                          * On exit, the RETURN REGISTER contains:
1115                          * - 0 if the rename is successful.
1116                          * - A nonzero, host-specific error code if the rename fails.
1117                          */
1118                         retval = semihosting_read_fields(target, 4, fields);
1119                         if (retval != ERROR_OK)
1120                                 return retval;
1121                         else {
1122                                 uint64_t addr1 = semihosting_get_field(target, 0, fields);
1123                                 size_t len1 = semihosting_get_field(target, 1, fields);
1124                                 uint64_t addr2 = semihosting_get_field(target, 2, fields);
1125                                 size_t len2 = semihosting_get_field(target, 3, fields);
1126                                 if (semihosting->is_fileio) {
1127                                         semihosting->hit_fileio = true;
1128                                         fileio_info->identifier = "rename";
1129                                         fileio_info->param_1 = addr1;
1130                                         fileio_info->param_2 = len1;
1131                                         fileio_info->param_3 = addr2;
1132                                         fileio_info->param_4 = len2;
1133                                 } else {
1134                                         uint8_t *fn1 = malloc(len1+1);
1135                                         uint8_t *fn2 = malloc(len2+1);
1136                                         if (!fn1 || !fn2) {
1137                                                 free(fn1);
1138                                                 free(fn2);
1139                                                 semihosting->result = -1;
1140                                                 semihosting->sys_errno = ENOMEM;
1141                                         } else {
1142                                                 retval = target_read_memory(target, addr1, 1, len1,
1143                                                                 fn1);
1144                                                 if (retval != ERROR_OK) {
1145                                                         free(fn1);
1146                                                         free(fn2);
1147                                                         return retval;
1148                                                 }
1149                                                 retval = target_read_memory(target, addr2, 1, len2,
1150                                                                 fn2);
1151                                                 if (retval != ERROR_OK) {
1152                                                         free(fn1);
1153                                                         free(fn2);
1154                                                         return retval;
1155                                                 }
1156                                                 fn1[len1] = 0;
1157                                                 fn2[len2] = 0;
1158                                                 semihosting->result = rename((char *)fn1,
1159                                                                 (char *)fn2);
1160                                                 semihosting->sys_errno = errno;
1161                                                 LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2,
1162                                                         (int)semihosting->result);
1163
1164                                                 free(fn1);
1165                                                 free(fn2);
1166                                         }
1167                                 }
1168                         }
1169                         break;
1170
1171                 case SEMIHOSTING_SYS_SEEK:      /* 0x0A */
1172                         /*
1173                          * Seeks to a specified position in a file using an offset
1174                          * specified from the start of the file. The file is assumed
1175                          * to be a byte array and the offset is given in bytes.
1176                          *
1177                          * Entry
1178                          * On entry, the PARAMETER REGISTER contains a pointer to a
1179                          * two-field data block:
1180                          * - field 1 A handle for a seekable file object.
1181                          * - field 2 The absolute byte position to seek to.
1182                          *
1183                          * Return
1184                          * On exit, the RETURN REGISTER contains:
1185                          * - 0 if the request is successful.
1186                          * - A negative value if the request is not successful.
1187                          * Use SYS_ERRNO to read the value of the host errno variable
1188                          * describing the error.
1189                          *
1190                          * Note: The effect of seeking outside the current extent of
1191                          * the file object is undefined.
1192                          */
1193                         retval = semihosting_read_fields(target, 2, fields);
1194                         if (retval != ERROR_OK)
1195                                 return retval;
1196                         else {
1197                                 int fd = semihosting_get_field(target, 0, fields);
1198                                 off_t pos = semihosting_get_field(target, 1, fields);
1199                                 if (semihosting->is_fileio) {
1200                                         semihosting->hit_fileio = true;
1201                                         fileio_info->identifier = "lseek";
1202                                         fileio_info->param_1 = fd;
1203                                         fileio_info->param_2 = pos;
1204                                         fileio_info->param_3 = SEEK_SET;
1205                                 } else {
1206                                         semihosting->result = lseek(fd, pos, SEEK_SET);
1207                                         semihosting->sys_errno = errno;
1208                                         LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos,
1209                                                 (int)semihosting->result);
1210                                         if (semihosting->result == pos)
1211                                                 semihosting->result = 0;
1212                                 }
1213                         }
1214                         break;
1215
1216                 case SEMIHOSTING_SYS_SYSTEM:    /* 0x12 */
1217                         /*
1218                          * Passes a command to the host command-line interpreter.
1219                          * This enables you to execute a system command such as dir,
1220                          * ls, or pwd. The terminal I/O is on the host, and is not
1221                          * visible to the target.
1222                          *
1223                          * Entry
1224                          * On entry, the PARAMETER REGISTER contains a pointer to a
1225                          * two-field argument block:
1226                          * - field 1 Points to a string to be passed to the host
1227                          * command-line interpreter.
1228                          * - field 2 The length of the string.
1229                          *
1230                          * Return
1231                          * On exit, the RETURN REGISTER contains the return status.
1232                          */
1233
1234                         /* Provide SYS_SYSTEM functionality.  Uses the
1235                          * libc system command, there may be a reason *NOT*
1236                          * to use this, but as I can't think of one, I
1237                          * implemented it this way.
1238                          */
1239                         retval = semihosting_read_fields(target, 2, fields);
1240                         if (retval != ERROR_OK)
1241                                 return retval;
1242                         else {
1243                                 uint64_t addr = semihosting_get_field(target, 0, fields);
1244                                 size_t len = semihosting_get_field(target, 1, fields);
1245                                 if (semihosting->is_fileio) {
1246                                         semihosting->hit_fileio = true;
1247                                         fileio_info->identifier = "system";
1248                                         fileio_info->param_1 = addr;
1249                                         fileio_info->param_2 = len;
1250                                 } else {
1251                                         uint8_t *cmd = malloc(len+1);
1252                                         if (!cmd) {
1253                                                 semihosting->result = -1;
1254                                                 semihosting->sys_errno = ENOMEM;
1255                                         } else {
1256                                                 retval = target_read_memory(target,
1257                                                                 addr,
1258                                                                 1,
1259                                                                 len,
1260                                                                 cmd);
1261                                                 if (retval != ERROR_OK) {
1262                                                         free(cmd);
1263                                                         return retval;
1264                                                 } else {
1265                                                         cmd[len] = 0;
1266                                                         semihosting->result = system(
1267                                                                         (const char *)cmd);
1268                                                         LOG_DEBUG("system('%s')=%d",
1269                                                                 cmd,
1270                                                                 (int)semihosting->result);
1271                                                 }
1272
1273                                                 free(cmd);
1274                                         }
1275                                 }
1276                         }
1277                         break;
1278
1279                 case SEMIHOSTING_SYS_TIME:      /* 0x11 */
1280                         /*
1281                          * Returns the number of seconds since 00:00 January 1, 1970.
1282                          * This value is real-world time, regardless of any debug agent
1283                          * configuration.
1284                          *
1285                          * Entry
1286                          * There are no parameters.
1287                          *
1288                          * Return
1289                          * On exit, the RETURN REGISTER contains the number of seconds.
1290                          */
1291                         semihosting->result = time(NULL);
1292                         break;
1293
1294                 case SEMIHOSTING_SYS_WRITE:     /* 0x05 */
1295                         /*
1296                          * Writes the contents of a buffer to a specified file at the
1297                          * current file position. The file position is specified either:
1298                          * - Explicitly, by a SYS_SEEK.
1299                          * - Implicitly as one byte beyond the previous SYS_READ or
1300                          * SYS_WRITE request.
1301                          *
1302                          * The file position is at the start of the file when the file
1303                          * is opened, and is lost when the file is closed.
1304                          *
1305                          * Perform the file operation as a single action whenever
1306                          * possible. For example, do not split a write of 16KB into
1307                          * four 4KB chunks unless there is no alternative.
1308                          *
1309                          * Entry
1310                          * On entry, the PARAMETER REGISTER contains a pointer to a
1311                          * three-field data block:
1312                          * - field 1 Contains a handle for a file previously opened
1313                          * with SYS_OPEN.
1314                          * - field 2 Points to the memory containing the data to be written.
1315                          * - field 3 Contains the number of bytes to be written from
1316                          * the buffer to the file.
1317                          *
1318                          * Return
1319                          * On exit, the RETURN REGISTER contains:
1320                          * - 0 if the call is successful.
1321                          * - The number of bytes that are not written, if there is an error.
1322                          */
1323                         retval = semihosting_read_fields(target, 3, fields);
1324                         if (retval != ERROR_OK)
1325                                 return retval;
1326                         else {
1327                                 int fd = semihosting_get_field(target, 0, fields);
1328                                 uint64_t addr = semihosting_get_field(target, 1, fields);
1329                                 size_t len = semihosting_get_field(target, 2, fields);
1330                                 if (semihosting->is_fileio) {
1331                                         semihosting->hit_fileio = true;
1332                                         fileio_info->identifier = "write";
1333                                         fileio_info->param_1 = fd;
1334                                         fileio_info->param_2 = addr;
1335                                         fileio_info->param_3 = len;
1336                                 } else {
1337                                         uint8_t *buf = malloc(len);
1338                                         if (!buf) {
1339                                                 semihosting->result = -1;
1340                                                 semihosting->sys_errno = ENOMEM;
1341                                         } else {
1342                                                 retval = target_read_buffer(target, addr, len, buf);
1343                                                 if (retval != ERROR_OK) {
1344                                                         free(buf);
1345                                                         return retval;
1346                                                 }
1347                                                 semihosting->result = semihosting_write(semihosting, fd, buf, len);
1348                                                 semihosting->sys_errno = errno;
1349                                                 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
1350                                                         fd,
1351                                                         addr,
1352                                                         len,
1353                                                         (int)semihosting->result);
1354                                                 if (semihosting->result >= 0) {
1355                                                         /* The number of bytes that are NOT written.
1356                                                          * */
1357                                                         semihosting->result = len -
1358                                                                 semihosting->result;
1359                                                 }
1360
1361                                                 free(buf);
1362                                         }
1363                                 }
1364                         }
1365                         break;
1366
1367                 case SEMIHOSTING_SYS_WRITEC:    /* 0x03 */
1368                         /*
1369                          * Writes a character byte, pointed to by the PARAMETER REGISTER,
1370                          * to the debug channel. When executed under a semihosting
1371                          * debugger, the character appears on the host debugger console.
1372                          *
1373                          * Entry
1374                          * On entry, the PARAMETER REGISTER contains a pointer to the
1375                          * character.
1376                          *
1377                          * Return
1378                          * None. The RETURN REGISTER is corrupted.
1379                          */
1380                         if (semihosting->is_fileio) {
1381                                 semihosting->hit_fileio = true;
1382                                 fileio_info->identifier = "write";
1383                                 fileio_info->param_1 = 1;
1384                                 fileio_info->param_2 = semihosting->param;
1385                                 fileio_info->param_3 = 1;
1386                         } else {
1387                                 uint64_t addr = semihosting->param;
1388                                 unsigned char c;
1389                                 retval = target_read_memory(target, addr, 1, 1, &c);
1390                                 if (retval != ERROR_OK)
1391                                         return retval;
1392                                 semihosting_putchar(semihosting, semihosting->stdout_fd, c);
1393                                 semihosting->result = 0;
1394                         }
1395                         break;
1396
1397                 case SEMIHOSTING_SYS_WRITE0:    /* 0x04 */
1398                         /*
1399                          * Writes a null-terminated string to the debug channel.
1400                          * When executed under a semihosting debugger, the characters
1401                          * appear on the host debugger console.
1402                          *
1403                          * Entry
1404                          * On entry, the PARAMETER REGISTER contains a pointer to the
1405                          * first byte of the string.
1406                          *
1407                          * Return
1408                          * None. The RETURN REGISTER is corrupted.
1409                          */
1410                         if (semihosting->is_fileio) {
1411                                 size_t count = 0;
1412                                 uint64_t addr = semihosting->param;
1413                                 for (;; addr++) {
1414                                         unsigned char c;
1415                                         retval = target_read_memory(target, addr, 1, 1, &c);
1416                                         if (retval != ERROR_OK)
1417                                                 return retval;
1418                                         if (c == '\0')
1419                                                 break;
1420                                         count++;
1421                                 }
1422                                 semihosting->hit_fileio = true;
1423                                 fileio_info->identifier = "write";
1424                                 fileio_info->param_1 = 1;
1425                                 fileio_info->param_2 = semihosting->param;
1426                                 fileio_info->param_3 = count;
1427                         } else {
1428                                 uint64_t addr = semihosting->param;
1429                                 do {
1430                                         unsigned char c;
1431                                         retval = target_read_memory(target, addr++, 1, 1, &c);
1432                                         if (retval != ERROR_OK)
1433                                                 return retval;
1434                                         if (!c)
1435                                                 break;
1436                                         semihosting_putchar(semihosting, semihosting->stdout_fd, c);
1437                                 } while (1);
1438                                 semihosting->result = 0;
1439                         }
1440                         break;
1441
1442                 case SEMIHOSTING_USER_CMD_0x100 ... SEMIHOSTING_USER_CMD_0x107:
1443                         /**
1444                          * This is a user defined operation (while user cmds 0x100-0x1ff
1445                          * are possible, only 0x100-0x107 are currently implemented).
1446                          *
1447                          * Reads the user operation parameters from target, then fires the
1448                          * corresponding target event. When the target callbacks returned,
1449                          * cleans up the command parameter buffer.
1450                          *
1451                          * Entry
1452                          * On entry, the PARAMETER REGISTER contains a pointer to a
1453                          * two-field data block:
1454                          * - field 1 Contains a pointer to the bound command parameter
1455                          * string
1456                          * - field 2 Contains the command parameter string length
1457                          *
1458                          * Return
1459                          * On exit, the RETURN REGISTER contains the return status.
1460                          */
1461                         if (semihosting->user_command_extension) {
1462                                 retval = semihosting->user_command_extension(target);
1463                                 if (retval != ERROR_NOT_IMPLEMENTED)
1464                                         break;
1465                                 /* If custom user command not handled, we are looking for the TCL handler */
1466                         }
1467
1468                         assert(!semihosting_user_op_params);
1469                         retval = semihosting_read_fields(target, 2, fields);
1470                         if (retval != ERROR_OK) {
1471                                 LOG_ERROR("Failed to read fields for user defined command"
1472                                                 " op=0x%x", semihosting->op);
1473                                 return retval;
1474                         }
1475
1476                         uint64_t addr = semihosting_get_field(target, 0, fields);
1477
1478                         size_t len = semihosting_get_field(target, 1, fields);
1479                         if (len > SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH) {
1480                                 LOG_ERROR("The maximum length for user defined command "
1481                                                 "parameter is %u, received length is %zu (op=0x%x)",
1482                                                 SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH,
1483                                                 len,
1484                                                 semihosting->op);
1485                                 return ERROR_FAIL;
1486                         }
1487
1488                         semihosting_user_op_params = malloc(len + 1);
1489                         if (!semihosting_user_op_params)
1490                                 return ERROR_FAIL;
1491                         semihosting_user_op_params[len] = 0;
1492
1493                         retval = target_read_buffer(target, addr, len,
1494                                         (uint8_t *)(semihosting_user_op_params));
1495                         if (retval != ERROR_OK) {
1496                                 LOG_ERROR("Failed to read from target, semihosting op=0x%x",
1497                                                 semihosting->op);
1498                                 free(semihosting_user_op_params);
1499                                 semihosting_user_op_params = NULL;
1500                                 return retval;
1501                         }
1502
1503                         target_handle_event(target, semihosting->op);
1504                         free(semihosting_user_op_params);
1505                         semihosting_user_op_params = NULL;
1506                         semihosting->result = 0;
1507                         break;
1508
1509                 case SEMIHOSTING_SYS_ELAPSED:   /* 0x30 */
1510                 /*
1511                  * Returns the number of elapsed target ticks since execution
1512                  * started.
1513                  * Use SYS_TICKFREQ to determine the tick frequency.
1514                  *
1515                  * Entry (32-bit)
1516                  * On entry, the PARAMETER REGISTER points to a two-field data
1517                  * block to be used for returning the number of elapsed ticks:
1518                  * - field 1 The least significant field and is at the low address.
1519                  * - field 2 The most significant field and is at the high address.
1520                  *
1521                  * Entry (64-bit)
1522                  * On entry the PARAMETER REGISTER points to a one-field data
1523                  * block to be used for returning the number of elapsed ticks:
1524                  * - field 1 The number of elapsed ticks as a 64-bit value.
1525                  *
1526                  * Return
1527                  * On exit:
1528                  * - On success, the RETURN REGISTER contains 0, the PARAMETER
1529                  * REGISTER is unchanged, and the data block pointed to by the
1530                  * PARAMETER REGISTER is filled in with the number of elapsed
1531                  * ticks.
1532                  * - On failure, the RETURN REGISTER contains -1, and the
1533                  * PARAMETER REGISTER contains -1.
1534                  *
1535                  * Note: Some semihosting implementations might not support this
1536                  * semihosting operation, and they always return -1 in the
1537                  * RETURN REGISTER.
1538                  */
1539
1540                 case SEMIHOSTING_SYS_TICKFREQ:  /* 0x31 */
1541                 /*
1542                  * Returns the tick frequency.
1543                  *
1544                  * Entry
1545                  * The PARAMETER REGISTER must contain 0 on entry to this routine.
1546                  *
1547                  * Return
1548                  * On exit, the RETURN REGISTER contains either:
1549                  * - The number of ticks per second.
1550                  * - â€“1 if the target does not know the value of one tick.
1551                  *
1552                  * Note: Some semihosting implementations might not support
1553                  * this semihosting operation, and they always return -1 in the
1554                  * RETURN REGISTER.
1555                  */
1556
1557                 case SEMIHOSTING_SYS_TMPNAM:    /* 0x0D */
1558                 /*
1559                  * Returns a temporary name for a file identified by a system
1560                  * file identifier.
1561                  *
1562                  * Entry
1563                  * On entry, the PARAMETER REGISTER contains a pointer to a
1564                  * three-word argument block:
1565                  * - field 1 A pointer to a buffer.
1566                  * - field 2 A target identifier for this filename. Its value
1567                  * must be an integer in the range 0-255.
1568                  * - field 3 Contains the length of the buffer. The length must
1569                  * be at least the value of L_tmpnam on the host system.
1570                  *
1571                  * Return
1572                  * On exit, the RETURN REGISTER contains:
1573                  * - 0 if the call is successful.
1574                  * - â€“1 if an error occurs.
1575                  *
1576                  * The buffer pointed to by the PARAMETER REGISTER contains
1577                  * the filename, prefixed with a suitable directory name.
1578                  * If you use the same target identifier again, the same
1579                  * filename is returned.
1580                  *
1581                  * Note: The returned string must be null-terminated.
1582                  */
1583
1584                 default:
1585                         fprintf(stderr, "semihosting: unsupported call %#x\n",
1586                                 (unsigned) semihosting->op);
1587                         semihosting->result = -1;
1588                         semihosting->sys_errno = ENOTSUP;
1589         }
1590
1591         if (!semihosting->hit_fileio) {
1592                 retval = semihosting->post_result(target);
1593                 if (retval != ERROR_OK) {
1594                         LOG_ERROR("Failed to post semihosting result");
1595                         return retval;
1596                 }
1597         }
1598
1599         return ERROR_OK;
1600 }
1601
1602 /* -------------------------------------------------------------------------
1603  * Local functions. */
1604
1605 static int semihosting_common_fileio_info(struct target *target,
1606         struct gdb_fileio_info *fileio_info)
1607 {
1608         struct semihosting *semihosting = target->semihosting;
1609         if (!semihosting)
1610                 return ERROR_FAIL;
1611
1612         /*
1613          * To avoid unnecessary duplication, semihosting prepares the
1614          * fileio_info structure out-of-band when the target halts. See
1615          * do_semihosting for more detail.
1616          */
1617         if (!semihosting->is_fileio || !semihosting->hit_fileio)
1618                 return ERROR_FAIL;
1619
1620         return ERROR_OK;
1621 }
1622
1623 static int semihosting_common_fileio_end(struct target *target, int result,
1624         int fileio_errno, bool ctrl_c)
1625 {
1626         struct gdb_fileio_info *fileio_info = target->fileio_info;
1627         struct semihosting *semihosting = target->semihosting;
1628         if (!semihosting)
1629                 return ERROR_FAIL;
1630
1631         /* clear pending status */
1632         semihosting->hit_fileio = false;
1633
1634         semihosting->result = result;
1635         semihosting->sys_errno = fileio_errno;
1636
1637         /*
1638          * Some fileio results do not match up with what the semihosting
1639          * operation expects; for these operations, we munge the results
1640          * below:
1641          */
1642         switch (semihosting->op) {
1643                 case SEMIHOSTING_SYS_WRITE:     /* 0x05 */
1644                         if (result < 0)
1645                                 semihosting->result = fileio_info->param_3;
1646                         else
1647                                 semihosting->result = 0;
1648                         break;
1649
1650                 case SEMIHOSTING_SYS_READ:      /* 0x06 */
1651                         if (result == (int)fileio_info->param_3)
1652                                 semihosting->result = 0;
1653                         if (result <= 0)
1654                                 semihosting->result = fileio_info->param_3;
1655                         break;
1656
1657                 case SEMIHOSTING_SYS_SEEK:      /* 0x0a */
1658                         if (result > 0)
1659                                 semihosting->result = 0;
1660                         break;
1661         }
1662
1663         return semihosting->post_result(target);
1664 }
1665
1666 /* -------------------------------------------------------------------------
1667  * Utility functions. */
1668
1669 /**
1670  * Read all fields of a command from target to buffer.
1671  */
1672 int semihosting_read_fields(struct target *target, size_t number,
1673         uint8_t *fields)
1674 {
1675         struct semihosting *semihosting = target->semihosting;
1676         /* Use 4-byte multiples to trigger fast memory access. */
1677         return target_read_memory(target, semihosting->param, 4,
1678                         number * (semihosting->word_size_bytes / 4), fields);
1679 }
1680
1681 /**
1682  * Write all fields of a command from buffer to target.
1683  */
1684 int semihosting_write_fields(struct target *target, size_t number,
1685         uint8_t *fields)
1686 {
1687         struct semihosting *semihosting = target->semihosting;
1688         /* Use 4-byte multiples to trigger fast memory access. */
1689         return target_write_memory(target, semihosting->param, 4,
1690                         number * (semihosting->word_size_bytes / 4), fields);
1691 }
1692
1693 /**
1694  * Extract a field from the buffer, considering register size and endianness.
1695  */
1696 uint64_t semihosting_get_field(struct target *target, size_t index,
1697         uint8_t *fields)
1698 {
1699         struct semihosting *semihosting = target->semihosting;
1700         if (semihosting->word_size_bytes == 8)
1701                 return target_buffer_get_u64(target, fields + (index * 8));
1702         else
1703                 return target_buffer_get_u32(target, fields + (index * 4));
1704 }
1705
1706 /**
1707  * Store a field in the buffer, considering register size and endianness.
1708  */
1709 void semihosting_set_field(struct target *target, uint64_t value,
1710         size_t index,
1711         uint8_t *fields)
1712 {
1713         struct semihosting *semihosting = target->semihosting;
1714         if (semihosting->word_size_bytes == 8)
1715                 target_buffer_set_u64(target, fields + (index * 8), value);
1716         else
1717                 target_buffer_set_u32(target, fields + (index * 4), value);
1718 }
1719
1720 /* -------------------------------------------------------------------------
1721  * Semihosting redirect over TCP structs and functions */
1722
1723 static int semihosting_service_new_connection_handler(struct connection *connection)
1724 {
1725         struct semihosting_tcp_service *service = connection->service->priv;
1726         service->semihosting->tcp_connection = connection;
1727
1728         return ERROR_OK;
1729 }
1730
1731 static int semihosting_service_input_handler(struct connection *connection)
1732 {
1733         struct semihosting_tcp_service *service = connection->service->priv;
1734
1735         if (!connection->input_pending) {
1736                 /* consume received data, not for semihosting IO */
1737                 const int buf_len = 100;
1738                 char buf[buf_len];
1739                 int bytes_read = connection_read(connection, buf, buf_len);
1740
1741                 if (bytes_read == 0) {
1742                         return ERROR_SERVER_REMOTE_CLOSED;
1743                 } else if (bytes_read == -1) {
1744                         LOG_ERROR("error during read: %s", strerror(errno));
1745                         return ERROR_SERVER_REMOTE_CLOSED;
1746                 }
1747         } else if (service->error != ERROR_OK) {
1748                 return ERROR_SERVER_REMOTE_CLOSED;
1749         }
1750
1751         return ERROR_OK;
1752 }
1753
1754 static int semihosting_service_connection_closed_handler(struct connection *connection)
1755 {
1756         struct semihosting_tcp_service *service = connection->service->priv;
1757         if (service) {
1758                 free(service->name);
1759                 free(service);
1760         }
1761
1762         return ERROR_OK;
1763 }
1764
1765 static void semihosting_tcp_close_cnx(struct semihosting *semihosting)
1766 {
1767         if (!semihosting->tcp_connection)
1768                 return;
1769
1770         struct service *service = semihosting->tcp_connection->service;
1771         remove_service(service->name, service->port);
1772         semihosting->tcp_connection = NULL;
1773
1774 }
1775
1776 static const struct service_driver semihosting_service_driver = {
1777         .name = "semihosting",
1778         .new_connection_during_keep_alive_handler = NULL,
1779         .new_connection_handler = semihosting_service_new_connection_handler,
1780         .input_handler = semihosting_service_input_handler,
1781         .connection_closed_handler = semihosting_service_connection_closed_handler,
1782         .keep_client_alive_handler = NULL,
1783 };
1784
1785 /* -------------------------------------------------------------------------
1786  * Common semihosting commands handlers. */
1787
1788 COMMAND_HANDLER(handle_common_semihosting_command)
1789 {
1790         struct target *target = get_current_target(CMD_CTX);
1791
1792         if (!target) {
1793                 LOG_ERROR("No target selected");
1794                 return ERROR_FAIL;
1795         }
1796
1797         struct semihosting *semihosting = target->semihosting;
1798         if (!semihosting) {
1799                 command_print(CMD, "semihosting not supported for current target");
1800                 return ERROR_FAIL;
1801         }
1802
1803         if (CMD_ARGC > 0) {
1804                 int is_active;
1805
1806                 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1807
1808                 if (!target_was_examined(target)) {
1809                         LOG_ERROR("Target not examined yet");
1810                         return ERROR_FAIL;
1811                 }
1812
1813                 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1814                         LOG_ERROR("Failed to Configure semihosting");
1815                         return ERROR_FAIL;
1816                 }
1817
1818                 /* FIXME never let that "catch" be dropped! (???) */
1819                 semihosting->is_active = is_active;
1820         }
1821
1822         command_print(CMD, "semihosting is %s",
1823                 semihosting->is_active
1824                 ? "enabled" : "disabled");
1825
1826         return ERROR_OK;
1827 }
1828
1829 COMMAND_HANDLER(handle_common_semihosting_redirect_command)
1830 {
1831         struct target *target = get_current_target(CMD_CTX);
1832
1833         if (target == NULL) {
1834                 LOG_ERROR("No target selected");
1835                 return ERROR_FAIL;
1836         }
1837
1838         struct semihosting *semihosting = target->semihosting;
1839         if (!semihosting) {
1840                 command_print(CMD, "semihosting not supported for current target");
1841                 return ERROR_FAIL;
1842         }
1843
1844         if (!semihosting->is_active) {
1845                 command_print(CMD, "semihosting not yet enabled for current target");
1846                 return ERROR_FAIL;
1847         }
1848
1849         enum semihosting_redirect_config cfg;
1850         const char *port;
1851
1852         if (CMD_ARGC < 1)
1853                 return ERROR_COMMAND_SYNTAX_ERROR;
1854
1855         if (strcmp(CMD_ARGV[0], "disable") == 0) {
1856                 cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
1857                 if (CMD_ARGC > 1)
1858                         return ERROR_COMMAND_SYNTAX_ERROR;
1859         } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
1860                 if (CMD_ARGC < 2 || CMD_ARGC > 3)
1861                         return ERROR_COMMAND_SYNTAX_ERROR;
1862
1863                 port = CMD_ARGV[1];
1864
1865                 cfg = SEMIHOSTING_REDIRECT_CFG_ALL;
1866                 if (CMD_ARGC == 3) {
1867                         if (strcmp(CMD_ARGV[2], "debug") == 0)
1868                                 cfg = SEMIHOSTING_REDIRECT_CFG_DEBUG;
1869                         else if (strcmp(CMD_ARGV[2], "stdio") == 0)
1870                                 cfg = SEMIHOSTING_REDIRECT_CFG_STDIO;
1871                         else if (strcmp(CMD_ARGV[2], "all") != 0)
1872                                 return ERROR_COMMAND_SYNTAX_ERROR;
1873                 }
1874         } else {
1875                 return ERROR_COMMAND_SYNTAX_ERROR;
1876         }
1877
1878         semihosting_tcp_close_cnx(semihosting);
1879         semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
1880
1881         if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) {
1882                 struct semihosting_tcp_service *service =
1883                                 calloc(1, sizeof(struct semihosting_tcp_service));
1884                 if (!service) {
1885                         LOG_ERROR("Failed to allocate semihosting TCP service.");
1886                         return ERROR_FAIL;
1887                 }
1888
1889                 service->semihosting = semihosting;
1890
1891                 service->name = alloc_printf("%s semihosting service", target_name(target));
1892                 if (!service->name) {
1893                         LOG_ERROR("Out of memory");
1894                         free(service);
1895                         return ERROR_FAIL;
1896                 }
1897
1898                 int ret = add_service(&semihosting_service_driver,
1899                                 port, 1, service);
1900
1901                 if (ret != ERROR_OK) {
1902                         LOG_ERROR("failed to initialize %s", service->name);
1903                         free(service->name);
1904                         free(service);
1905                         return ERROR_FAIL;
1906                 }
1907         }
1908
1909         semihosting->redirect_cfg = cfg;
1910
1911         return ERROR_OK;
1912 }
1913
1914 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1915 {
1916         struct target *target = get_current_target(CMD_CTX);
1917
1918         if (!target) {
1919                 LOG_ERROR("No target selected");
1920                 return ERROR_FAIL;
1921         }
1922
1923         struct semihosting *semihosting = target->semihosting;
1924         if (!semihosting) {
1925                 command_print(CMD, "semihosting not supported for current target");
1926                 return ERROR_FAIL;
1927         }
1928
1929         if (!semihosting->is_active) {
1930                 command_print(CMD, "semihosting not yet enabled for current target");
1931                 return ERROR_FAIL;
1932         }
1933
1934         if (CMD_ARGC > 0)
1935                 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1936
1937         command_print(CMD, "semihosting fileio is %s",
1938                 semihosting->is_fileio
1939                 ? "enabled" : "disabled");
1940
1941         return ERROR_OK;
1942 }
1943
1944 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1945 {
1946         struct target *target = get_current_target(CMD_CTX);
1947         unsigned int i;
1948
1949         if (!target) {
1950                 LOG_ERROR("No target selected");
1951                 return ERROR_FAIL;
1952         }
1953
1954         struct semihosting *semihosting = target->semihosting;
1955         if (!semihosting) {
1956                 command_print(CMD, "semihosting not supported for current target");
1957                 return ERROR_FAIL;
1958         }
1959
1960         free(semihosting->cmdline);
1961         semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
1962
1963         for (i = 1; i < CMD_ARGC; i++) {
1964                 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
1965                 if (!cmdline)
1966                         break;
1967                 free(semihosting->cmdline);
1968                 semihosting->cmdline = cmdline;
1969         }
1970
1971         command_print(CMD, "semihosting command line is [%s]",
1972                 semihosting->cmdline);
1973
1974         return ERROR_OK;
1975 }
1976
1977 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
1978 {
1979         struct target *target = get_current_target(CMD_CTX);
1980
1981         if (!target) {
1982                 LOG_ERROR("No target selected");
1983                 return ERROR_FAIL;
1984         }
1985
1986         struct semihosting *semihosting = target->semihosting;
1987         if (!semihosting) {
1988                 command_print(CMD, "semihosting not supported for current target");
1989                 return ERROR_FAIL;
1990         }
1991
1992         if (!semihosting->is_active) {
1993                 command_print(CMD, "semihosting not yet enabled for current target");
1994                 return ERROR_FAIL;
1995         }
1996
1997         if (CMD_ARGC > 0)
1998                 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
1999
2000         command_print(CMD, "semihosting resumable exit is %s",
2001                 semihosting->has_resumable_exit
2002                 ? "enabled" : "disabled");
2003
2004         return ERROR_OK;
2005 }
2006
2007 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
2008 {
2009         struct target *target = get_current_target(CMD_CTX);
2010         struct semihosting *semihosting = target->semihosting;
2011
2012         if (CMD_ARGC)
2013                 return ERROR_COMMAND_SYNTAX_ERROR;
2014
2015         if (!semihosting->is_active) {
2016                 LOG_ERROR("semihosting not yet enabled for current target");
2017                 return ERROR_FAIL;
2018         }
2019
2020         if (!semihosting_user_op_params) {
2021                 LOG_ERROR("This command is usable only from a registered user "
2022                                 "semihosting event callback.");
2023                 return ERROR_FAIL;
2024         }
2025
2026         command_print_sameline(CMD, "%s", semihosting_user_op_params);
2027
2028         return ERROR_OK;
2029 }
2030
2031 COMMAND_HANDLER(handle_common_semihosting_basedir_command)
2032 {
2033         struct target *target = get_current_target(CMD_CTX);
2034
2035         if (CMD_ARGC > 1)
2036                 return ERROR_COMMAND_SYNTAX_ERROR;
2037
2038         if (!target) {
2039                 LOG_ERROR("No target selected");
2040                 return ERROR_FAIL;
2041         }
2042
2043         struct semihosting *semihosting = target->semihosting;
2044         if (!semihosting) {
2045                 command_print(CMD, "semihosting not supported for current target");
2046                 return ERROR_FAIL;
2047         }
2048
2049         if (!semihosting->is_active) {
2050                 command_print(CMD, "semihosting not yet enabled for current target");
2051                 return ERROR_FAIL;
2052         }
2053
2054         if (CMD_ARGC > 0) {
2055                 free(semihosting->basedir);
2056                 semihosting->basedir = strdup(CMD_ARGV[0]);
2057                 if (!semihosting->basedir) {
2058                         command_print(CMD, "semihosting failed to allocate memory for basedir!");
2059                         return ERROR_FAIL;
2060                 }
2061         }
2062
2063         command_print(CMD, "semihosting base dir: %s",
2064                 semihosting->basedir ? semihosting->basedir : "");
2065
2066         return ERROR_OK;
2067 }
2068
2069 const struct command_registration semihosting_common_handlers[] = {
2070         {
2071                 .name = "semihosting",
2072                 .handler = handle_common_semihosting_command,
2073                 .mode = COMMAND_EXEC,
2074                 .usage = "['enable'|'disable']",
2075                 .help = "activate support for semihosting operations",
2076         },
2077         {
2078                 .name = "semihosting_redirect",
2079                 .handler = handle_common_semihosting_redirect_command,
2080                 .mode = COMMAND_EXEC,
2081                 .usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2082                 .help = "redirect semihosting IO",
2083         },
2084         {
2085                 .name = "semihosting_cmdline",
2086                 .handler = handle_common_semihosting_cmdline,
2087                 .mode = COMMAND_EXEC,
2088                 .usage = "arguments",
2089                 .help = "command line arguments to be passed to program",
2090         },
2091         {
2092                 .name = "semihosting_fileio",
2093                 .handler = handle_common_semihosting_fileio_command,
2094                 .mode = COMMAND_EXEC,
2095                 .usage = "['enable'|'disable']",
2096                 .help = "activate support for semihosting fileio operations",
2097         },
2098         {
2099                 .name = "semihosting_resexit",
2100                 .handler = handle_common_semihosting_resumable_exit_command,
2101                 .mode = COMMAND_EXEC,
2102                 .usage = "['enable'|'disable']",
2103                 .help = "activate support for semihosting resumable exit",
2104         },
2105         {
2106                 .name = "semihosting_read_user_param",
2107                 .handler = handle_common_semihosting_read_user_param_command,
2108                 .mode = COMMAND_EXEC,
2109                 .usage = "",
2110                 .help = "read parameters in semihosting-user-cmd-0x10X callbacks",
2111         },
2112         {
2113                 .name = "semihosting_basedir",
2114                 .handler = handle_common_semihosting_basedir_command,
2115                 .mode = COMMAND_EXEC,
2116                 .usage = "[dir]",
2117                 .help = "set the base directory for semihosting I/O operations",
2118         },
2119         COMMAND_REGISTRATION_DONE
2120 };