ffed7350edd5794612b0b6ed9ec1de4909af57a3
[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 static const int open_modeflags[12] = {
56         O_RDONLY,
57         O_RDONLY | O_BINARY,
58         O_RDWR,
59         O_RDWR | O_BINARY,
60         O_WRONLY | O_CREAT | O_TRUNC,
61         O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
62         O_RDWR | O_CREAT | O_TRUNC,
63         O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
64         O_WRONLY | O_CREAT | O_APPEND,
65         O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
66         O_RDWR | O_CREAT | O_APPEND,
67         O_RDWR | O_CREAT | O_APPEND | O_BINARY
68 };
69
70 static int semihosting_common_fileio_info(struct target *target,
71         struct gdb_fileio_info *fileio_info);
72 static int semihosting_common_fileio_end(struct target *target, int result,
73         int fileio_errno, bool ctrl_c);
74
75 static int semihosting_read_fields(struct target *target, size_t number,
76         uint8_t *fields);
77 static int semihosting_write_fields(struct target *target, size_t number,
78         uint8_t *fields);
79 static uint64_t semihosting_get_field(struct target *target, size_t index,
80         uint8_t *fields);
81 static void semihosting_set_field(struct target *target, uint64_t value,
82         size_t index,
83         uint8_t *fields);
84
85 /* Attempts to include gdb_server.h failed. */
86 extern int gdb_actual_connections;
87
88 /**
89  * Initialize common semihosting support.
90  *
91  * @param target Pointer to the target to initialize.
92  * @param setup
93  * @param post_result
94  * @return An error status if there is a problem during initialization.
95  */
96 int semihosting_common_init(struct target *target, void *setup,
97         void *post_result)
98 {
99         LOG_DEBUG(" ");
100
101         target->fileio_info = malloc(sizeof(*target->fileio_info));
102         if (target->fileio_info == NULL) {
103                 LOG_ERROR("out of memory");
104                 return ERROR_FAIL;
105         }
106         memset(target->fileio_info, 0, sizeof(*target->fileio_info));
107
108         struct semihosting *semihosting;
109         semihosting = malloc(sizeof(*target->semihosting));
110         if (semihosting == NULL) {
111                 LOG_ERROR("out of memory");
112                 return ERROR_FAIL;
113         }
114
115         semihosting->is_active = false;
116         semihosting->is_fileio = false;
117         semihosting->hit_fileio = false;
118         semihosting->is_resumable = false;
119         semihosting->has_resumable_exit = false;
120         semihosting->word_size_bytes = 0;
121         semihosting->op = -1;
122         semihosting->param = 0;
123         semihosting->result = -1;
124         semihosting->sys_errno = -1;
125         semihosting->cmdline = NULL;
126
127         /* If possible, update it in setup(). */
128         semihosting->setup_time = clock();
129
130         semihosting->setup = setup;
131         semihosting->post_result = post_result;
132
133         target->semihosting = semihosting;
134
135         target->type->get_gdb_fileio_info = semihosting_common_fileio_info;
136         target->type->gdb_fileio_end = semihosting_common_fileio_end;
137
138         return ERROR_OK;
139 }
140
141 /**
142  * Portable implementation of ARM semihosting calls.
143  * Performs the currently pending semihosting operation
144  * encoded in target->semihosting.
145  */
146 int semihosting_common(struct target *target)
147 {
148         struct semihosting *semihosting = target->semihosting;
149         if (!semihosting) {
150                 /* Silently ignore if the semihosting field was not set. */
151                 return ERROR_OK;
152         }
153
154         struct gdb_fileio_info *fileio_info = target->fileio_info;
155
156         /*
157          * By default return an error.
158          * The actual result must be set by each function
159          */
160         semihosting->result = -1;
161
162         /* Most operations are resumable, except the two exit calls. */
163         semihosting->is_resumable = true;
164
165         int retval;
166
167         /* Enough space to hold 4 long words. */
168         uint8_t fields[4*8];
169
170         LOG_DEBUG("op=0x%x, param=0x%" PRIx64, (int)semihosting->op,
171                 semihosting->param);
172
173         switch (semihosting->op) {
174
175                 case SEMIHOSTING_SYS_CLOCK:     /* 0x10 */
176                         /*
177                          * Returns the number of centiseconds (hundredths of a second)
178                          * since the execution started.
179                          *
180                          * Values returned can be of limited use for some benchmarking
181                          * purposes because of communication overhead or other
182                          * agent-specific factors. For example, with a debug hardware
183                          * unit the request is passed back to the host for execution.
184                          * This can lead to unpredictable delays in transmission and
185                          * process scheduling.
186                          *
187                          * Use this function to calculate time intervals, by calculating
188                          * differences between intervals with and without the code
189                          * sequence to be timed.
190                          *
191                          * Entry
192                          * The PARAMETER REGISTER must contain 0. There are no other
193                          * parameters.
194                          *
195                          * Return
196                          * On exit, the RETURN REGISTER contains:
197                          * - The number of centiseconds since some arbitrary start
198                          * point, if the call is successful.
199                          * - –1 if the call is not successful. For example, because
200                          * of a communications error.
201                          */
202                 {
203                         clock_t delta = clock() - semihosting->setup_time;
204
205                         semihosting->result = delta / (CLOCKS_PER_SEC / 100);
206                 }
207                 break;
208
209                 case SEMIHOSTING_SYS_CLOSE:     /* 0x02 */
210                         /*
211                          * Closes a file on the host system. The handle must reference
212                          * a file that was opened with SYS_OPEN.
213                          *
214                          * Entry
215                          * On entry, the PARAMETER REGISTER contains a pointer to a
216                          * one-field argument block:
217                          * - field 1 Contains a handle for an open file.
218                          *
219                          * Return
220                          * On exit, the RETURN REGISTER contains:
221                          * - 0 if the call is successful
222                          * - –1 if the call is not successful.
223                          */
224                         retval = semihosting_read_fields(target, 1, fields);
225                         if (retval != ERROR_OK)
226                                 return retval;
227                         else {
228                                 int fd = semihosting_get_field(target, 0, fields);
229                                 /* Do not allow to close OpenOCD's own standard streams */
230                                 if (fd == 0 || fd == 1 || fd == 2) {
231                                         LOG_DEBUG("ignoring semihosting attempt to close %s",
232                                                         (fd == 0) ? "stdin" :
233                                                         (fd == 1) ? "stdout" : "stderr");
234                                         /* Just pretend success */
235                                         if (semihosting->is_fileio) {
236                                                 semihosting->result = 0;
237                                         } else {
238                                                 semihosting->result = 0;
239                                                 semihosting->sys_errno = 0;
240                                         }
241                                         break;
242                                 }
243                                 /* Close the descriptor */
244                                 if (semihosting->is_fileio) {
245                                         semihosting->hit_fileio = true;
246                                         fileio_info->identifier = "close";
247                                         fileio_info->param_1 = fd;
248                                 } else {
249                                         semihosting->result = close(fd);
250                                         semihosting->sys_errno = errno;
251                                         LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result);
252                                 }
253                         }
254                         break;
255
256                 case SEMIHOSTING_SYS_ERRNO:     /* 0x13 */
257                         /*
258                          * Returns the value of the C library errno variable that is
259                          * associated with the semihosting implementation. The errno
260                          * variable can be set by a number of C library semihosted
261                          * functions, including:
262                          * - SYS_REMOVE
263                          * - SYS_OPEN
264                          * - SYS_CLOSE
265                          * - SYS_READ
266                          * - SYS_WRITE
267                          * - SYS_SEEK.
268                          *
269                          * Whether errno is set or not, and to what value, is entirely
270                          * host-specific, except where the ISO C standard defines the
271                          * behavior.
272                          *
273                          * Entry
274                          * There are no parameters. The PARAMETER REGISTER must be 0.
275                          *
276                          * Return
277                          * On exit, the RETURN REGISTER contains the value of the C
278                          * library errno variable.
279                          */
280                         semihosting->result = semihosting->sys_errno;
281                         break;
282
283                 case SEMIHOSTING_SYS_EXIT:      /* 0x18 */
284                         /*
285                          * Note: SYS_EXIT was called angel_SWIreason_ReportException in
286                          * previous versions of the documentation.
287                          *
288                          * An application calls this operation to report an exception
289                          * to the debugger directly. The most common use is to report
290                          * that execution has completed, using ADP_Stopped_ApplicationExit.
291                          *
292                          * Note: This semihosting operation provides no means for 32-bit
293                          * callers to indicate an application exit with a specified exit
294                          * code. Semihosting callers may prefer to check for the presence
295                          * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use
296                          * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it
297                          * is available.
298                          *
299                          * Entry (32-bit)
300                          * On entry, the PARAMETER register is set to a reason code
301                          * describing the cause of the trap. Not all semihosting client
302                          * implementations will necessarily trap every corresponding
303                          * event. Important reason codes are:
304                          *
305                          * - ADP_Stopped_ApplicationExit 0x20026
306                          * - ADP_Stopped_RunTimeErrorUnknown 0x20023
307                          *
308                          * Entry (64-bit)
309                          * On entry, the PARAMETER REGISTER contains a pointer to a
310                          * two-field argument block:
311                          * - field 1 The exception type, which is one of the set of
312                          * reason codes in the above tables.
313                          * - field 2 A subcode, whose meaning depends on the reason
314                          * code in field 1.
315                          * In particular, if field 1 is ADP_Stopped_ApplicationExit
316                          * then field 2 is an exit status code, as passed to the C
317                          * standard library exit() function. A simulator receiving
318                          * this request must notify a connected debugger, if present,
319                          * and then exit with the specified status.
320                          *
321                          * Return
322                          * No return is expected from these calls. However, it is
323                          * possible for the debugger to request that the application
324                          * continues by performing an RDI_Execute request or equivalent.
325                          * In this case, execution continues with the registers as they
326                          * were on entry to the operation, or as subsequently modified
327                          * by the debugger.
328                          */
329                         if (semihosting->word_size_bytes == 8) {
330                                 retval = semihosting_read_fields(target, 2, fields);
331                                 if (retval != ERROR_OK)
332                                         return retval;
333                                 else {
334                                         int type = semihosting_get_field(target, 0, fields);
335                                         int code = semihosting_get_field(target, 1, fields);
336
337                                         if (type == ADP_STOPPED_APPLICATION_EXIT) {
338                                                 if (!gdb_actual_connections)
339                                                         exit(code);
340                                                 else {
341                                                         fprintf(stderr,
342                                                                 "semihosting: *** application exited with %d ***\n",
343                                                                 code);
344                                                 }
345                                         } else {
346                                                 fprintf(stderr,
347                                                         "semihosting: application exception %#x\n",
348                                                         type);
349                                         }
350                                 }
351                         } else {
352                                 if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) {
353                                         if (!gdb_actual_connections)
354                                                 exit(0);
355                                         else {
356                                                 fprintf(stderr,
357                                                         "semihosting: *** application exited normally ***\n");
358                                         }
359                                 } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) {
360                                         /* Chosen more or less arbitrarily to have a nicer message,
361                                          * otherwise all other return the same exit code 1. */
362                                         if (!gdb_actual_connections)
363                                                 exit(1);
364                                         else {
365                                                 fprintf(stderr,
366                                                         "semihosting: *** application exited with error ***\n");
367                                         }
368                                 } else {
369                                         if (!gdb_actual_connections)
370                                                 exit(1);
371                                         else {
372                                                 fprintf(stderr,
373                                                         "semihosting: application exception %#x\n",
374                                                         (unsigned) semihosting->param);
375                                         }
376                                 }
377                         }
378                         if (!semihosting->has_resumable_exit) {
379                                 semihosting->is_resumable = false;
380                                 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
381                         }
382                         break;
383
384                 case SEMIHOSTING_SYS_EXIT_EXTENDED:     /* 0x20 */
385                         /*
386                          * This operation is only supported if the semihosting extension
387                          * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is
388                          * reported using feature byte 0, bit 0. If this extension is
389                          * supported, then the implementation provides a means to
390                          * report a normal exit with a nonzero exit status in both 32-bit
391                          * and 64-bit semihosting APIs.
392                          *
393                          * The implementation must provide the semihosting call
394                          * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs.
395                          *
396                          * SYS_EXIT_EXTENDED is used by an application to report an
397                          * exception or exit to the debugger directly. The most common
398                          * use is to report that execution has completed, using
399                          * ADP_Stopped_ApplicationExit.
400                          *
401                          * Entry
402                          * On entry, the PARAMETER REGISTER contains a pointer to a
403                          * two-field argument block:
404                          * - field 1 The exception type, which should be one of the set
405                          * of reason codes that are documented for the SYS_EXIT
406                          * (0x18) call. For example, ADP_Stopped_ApplicationExit.
407                          * - field 2 A subcode, whose meaning depends on the reason
408                          * code in field 1. In particular, if field 1 is
409                          * ADP_Stopped_ApplicationExit then field 2 is an exit status
410                          * code, as passed to the C standard library exit() function.
411                          * A simulator receiving this request must notify a connected
412                          * debugger, if present, and then exit with the specified status.
413                          *
414                          * Return
415                          * No return is expected from these calls.
416                          *
417                          * For the A64 API, this call is identical to the behavior of
418                          * the mandatory SYS_EXIT (0x18) call. If this extension is
419                          * supported, then both calls must be implemented.
420                          */
421                         retval = semihosting_read_fields(target, 2, fields);
422                         if (retval != ERROR_OK)
423                                 return retval;
424                         else {
425                                 int type = semihosting_get_field(target, 0, fields);
426                                 int code = semihosting_get_field(target, 1, fields);
427
428                                 if (type == ADP_STOPPED_APPLICATION_EXIT) {
429                                         if (!gdb_actual_connections)
430                                                 exit(code);
431                                         else {
432                                                 fprintf(stderr,
433                                                         "semihosting: *** application exited with %d ***\n",
434                                                         code);
435                                         }
436                                 } else {
437                                         fprintf(stderr, "semihosting: exception %#x\n",
438                                                 type);
439                                 }
440                         }
441                         if (!semihosting->has_resumable_exit) {
442                                 semihosting->is_resumable = false;
443                                 return target_call_event_callbacks(target, TARGET_EVENT_HALTED);
444                         }
445                         break;
446
447                 case SEMIHOSTING_SYS_FLEN:      /* 0x0C */
448                         /*
449                          * Returns the length of a specified file.
450                          *
451                          * Entry
452                          * On entry, the PARAMETER REGISTER contains a pointer to a
453                          * one-field argument block:
454                          * - field 1 A handle for a previously opened, seekable file
455                          * object.
456                          *
457                          * Return
458                          * On exit, the RETURN REGISTER contains:
459                          * - The current length of the file object, if the call is
460                          * successful.
461                          * - –1 if an error occurs.
462                          */
463                         if (semihosting->is_fileio) {
464                                 semihosting->result = -1;
465                                 semihosting->sys_errno = EINVAL;
466                         }
467                         retval = semihosting_read_fields(target, 1, fields);
468                         if (retval != ERROR_OK)
469                                 return retval;
470                         else {
471                                 int fd = semihosting_get_field(target, 0, fields);
472                                 struct stat buf;
473                                 semihosting->result = fstat(fd, &buf);
474                                 if (semihosting->result == -1) {
475                                         semihosting->sys_errno = errno;
476                                         LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
477                                         break;
478                                 }
479                                 LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result);
480                                 semihosting->result = buf.st_size;
481                         }
482                         break;
483
484                 case SEMIHOSTING_SYS_GET_CMDLINE:       /* 0x15 */
485                         /*
486                          * Returns the command line that is used for the call to the
487                          * executable, that is, argc and argv.
488                          *
489                          * Entry
490                          * On entry, the PARAMETER REGISTER points to a two-field data
491                          * block to be used for returning the command string and its length:
492                          * - field 1 A pointer to a buffer of at least the size that is
493                          * specified in field 2.
494                          * - field 2 The length of the buffer in bytes.
495                          *
496                          * Return
497                          * On exit:
498                          * If the call is successful, then the RETURN REGISTER contains 0,
499                          * the PARAMETER REGISTER is unchanged, and the data block is
500                          * updated as follows:
501                          * - field 1 A pointer to a null-terminated string of the command
502                          * line.
503                          * - field 2 The length of the string in bytes.
504                          * If the call is not successful, then the RETURN REGISTER
505                          * contains -1.
506                          *
507                          * Note: The semihosting implementation might impose limits on
508                          * the maximum length of the string that can be transferred.
509                          * However, the implementation must be able to support a
510                          * command-line length of at least 80 bytes.
511                          */
512                         retval = semihosting_read_fields(target, 2, fields);
513                         if (retval != ERROR_OK)
514                                 return retval;
515                         else {
516                                 uint64_t addr = semihosting_get_field(target, 0, fields);
517                                 size_t size = semihosting_get_field(target, 1, fields);
518
519                                 char *arg = semihosting->cmdline != NULL ?
520                                         semihosting->cmdline : "";
521                                 uint32_t len = strlen(arg) + 1;
522                                 if (len > size)
523                                         semihosting->result = -1;
524                                 else {
525                                         semihosting_set_field(target, len, 1, fields);
526                                         retval = target_write_buffer(target, addr, len,
527                                                         (uint8_t *)arg);
528                                         if (retval != ERROR_OK)
529                                                 return retval;
530                                         semihosting->result = 0;
531
532                                         retval = semihosting_write_fields(target, 2, fields);
533                                         if (retval != ERROR_OK)
534                                                 return retval;
535                                 }
536                                 LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg,
537                                         (int)semihosting->result);
538                         }
539                         break;
540
541                 case SEMIHOSTING_SYS_HEAPINFO:  /* 0x16 */
542                         /*
543                          * Returns the system stack and heap parameters.
544                          *
545                          * Entry
546                          * On entry, the PARAMETER REGISTER contains the address of a
547                          * pointer to a four-field data block. The contents of the data
548                          * block are filled by the function. The following C-like
549                          * pseudocode describes the layout of the block:
550                          * struct block {
551                          *   void* heap_base;
552                          *   void* heap_limit;
553                          *   void* stack_base;
554                          *   void* stack_limit;
555                          * };
556                          *
557                          * Return
558                          * On exit, the PARAMETER REGISTER is unchanged and the data
559                          * block has been updated.
560                          */
561                         retval = semihosting_read_fields(target, 1, fields);
562                         if (retval != ERROR_OK)
563                                 return retval;
564                         else {
565                                 uint64_t addr = semihosting_get_field(target, 0, fields);
566                                 /* tell the remote we have no idea */
567                                 memset(fields, 0, 4 * semihosting->word_size_bytes);
568                                 retval = target_write_memory(target, addr, 4,
569                                                 semihosting->word_size_bytes,
570                                                 fields);
571                                 if (retval != ERROR_OK)
572                                         return retval;
573                                 semihosting->result = 0;
574                         }
575                         break;
576
577                 case SEMIHOSTING_SYS_ISERROR:   /* 0x08 */
578                         /*
579                          * Determines whether the return code from another semihosting
580                          * call is an error status or not.
581                          *
582                          * This call is passed a parameter block containing the error
583                          * code to examine.
584                          *
585                          * Entry
586                          * On entry, the PARAMETER REGISTER contains a pointer to a
587                          * one-field data block:
588                          * - field 1 The required status word to check.
589                          *
590                          * Return
591                          * On exit, the RETURN REGISTER contains:
592                          * - 0 if the status field is not an error indication
593                          * - A nonzero value if the status field is an error indication.
594                          */
595                         retval = semihosting_read_fields(target, 1, fields);
596                         if (retval != ERROR_OK)
597                                 return retval;
598
599                         uint64_t code = semihosting_get_field(target, 0, fields);
600                         semihosting->result = (code != 0);
601                         break;
602
603                 case SEMIHOSTING_SYS_ISTTY:     /* 0x09 */
604                         /*
605                          * Checks whether a file is connected to an interactive device.
606                          *
607                          * Entry
608                          * On entry, the PARAMETER REGISTER contains a pointer to a
609                          * one-field argument block:
610                          * field 1 A handle for a previously opened file object.
611                          *
612                          * Return
613                          * On exit, the RETURN REGISTER contains:
614                          * - 1 if the handle identifies an interactive device.
615                          * - 0 if the handle identifies a file.
616                          * - A value other than 1 or 0 if an error occurs.
617                          */
618                         if (semihosting->is_fileio) {
619                                 semihosting->hit_fileio = true;
620                                 fileio_info->identifier = "isatty";
621                                 fileio_info->param_1 = semihosting->param;
622                         } else {
623                                 retval = semihosting_read_fields(target, 1, fields);
624                                 if (retval != ERROR_OK)
625                                         return retval;
626                                 int fd = semihosting_get_field(target, 0, fields);
627                                 semihosting->result = isatty(fd);
628                                 semihosting->sys_errno = errno;
629                                 LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result);
630                         }
631                         break;
632
633                 case SEMIHOSTING_SYS_OPEN:      /* 0x01 */
634                         /*
635                          * Opens a file on the host system.
636                          *
637                          * The file path is specified either as relative to the current
638                          * directory of the host process, or absolute, using the path
639                          * conventions of the host operating system.
640                          *
641                          * Semihosting implementations must support opening the special
642                          * path name :semihosting-features as part of the semihosting
643                          * extensions reporting mechanism.
644                          *
645                          * ARM targets interpret the special path name :tt as meaning
646                          * the console input stream, for an open-read or the console
647                          * output stream, for an open-write. Opening these streams is
648                          * performed as part of the standard startup code for those
649                          * applications that reference the C stdio streams. The
650                          * semihosting extension SH_EXT_STDOUT_STDERR allows the
651                          * semihosting caller to open separate output streams
652                          * corresponding to stdout and stderr. This extension is
653                          * reported using feature byte 0, bit 1. Use SYS_OPEN with
654                          * the special path name :semihosting-features to access the
655                          * feature bits.
656                          *
657                          * If this extension is supported, the implementation must
658                          * support the following additional semantics to SYS_OPEN:
659                          * - If the special path name :tt is opened with an fopen
660                          * mode requesting write access (w, wb, w+, or w+b), then
661                          * this is a request to open stdout.
662                          * - If the special path name :tt is opened with a mode
663                          * requesting append access (a, ab, a+, or a+b), then this is
664                          * a request to open stderr.
665                          *
666                          * Entry
667                          * On entry, the PARAMETER REGISTER contains a pointer to a
668                          * three-field argument block:
669                          * - field 1 A pointer to a null-terminated string containing
670                          * a file or device name.
671                          * - field 2 An integer that specifies the file opening mode.
672                          * - field 3 An integer that gives the length of the string
673                          * pointed to by field 1.
674                          *
675                          * The length does not include the terminating null character
676                          * that must be present.
677                          *
678                          * Return
679                          * On exit, the RETURN REGISTER contains:
680                          * - A nonzero handle if the call is successful.
681                          * - –1 if the call is not successful.
682                          */
683                         retval = semihosting_read_fields(target, 3, fields);
684                         if (retval != ERROR_OK)
685                                 return retval;
686                         else {
687                                 uint64_t addr = semihosting_get_field(target, 0, fields);
688                                 uint32_t mode = semihosting_get_field(target, 1, fields);
689                                 size_t len = semihosting_get_field(target, 2, fields);
690
691                                 if (mode > 11) {
692                                         semihosting->result = -1;
693                                         semihosting->sys_errno = EINVAL;
694                                         break;
695                                 }
696                                 uint8_t *fn = malloc(len+1);
697                                 if (!fn) {
698                                         semihosting->result = -1;
699                                         semihosting->sys_errno = ENOMEM;
700                                 } else {
701                                         retval = target_read_memory(target, addr, 1, len, fn);
702                                         if (retval != ERROR_OK) {
703                                                 free(fn);
704                                                 return retval;
705                                         }
706                                         fn[len] = 0;
707                                         /* TODO: implement the :semihosting-features special file.
708                                          * */
709                                         if (semihosting->is_fileio) {
710                                                 if (strcmp((char *)fn, ":semihosting-features") == 0) {
711                                                         semihosting->result = -1;
712                                                         semihosting->sys_errno = EINVAL;
713                                                 } else if (strcmp((char *)fn, ":tt") == 0) {
714                                                         if (mode == 0)
715                                                                 semihosting->result = 0;
716                                                         else if (mode == 4)
717                                                                 semihosting->result = 1;
718                                                         else if (mode == 8)
719                                                                 semihosting->result = 2;
720                                                         else
721                                                                 semihosting->result = -1;
722                                                 } else {
723                                                         semihosting->hit_fileio = true;
724                                                         fileio_info->identifier = "open";
725                                                         fileio_info->param_1 = addr;
726                                                         fileio_info->param_2 = len;
727                                                         fileio_info->param_3 = open_modeflags[mode];
728                                                         fileio_info->param_4 = 0644;
729                                                 }
730                                         } else {
731                                                 if (strcmp((char *)fn, ":tt") == 0) {
732                                                         /* Mode is:
733                                                          * - 0-3 ("r") for stdin,
734                                                          * - 4-7 ("w") for stdout,
735                                                          * - 8-11 ("a") for stderr */
736                                                         if (mode < 4) {
737                                                                 semihosting->result = dup(
738                                                                                 STDIN_FILENO);
739                                                                 semihosting->sys_errno = errno;
740                                                                 LOG_DEBUG("dup(STDIN)=%d",
741                                                                         (int)semihosting->result);
742                                                         } else if (mode < 8) {
743                                                                 semihosting->result = dup(
744                                                                                 STDOUT_FILENO);
745                                                                 semihosting->sys_errno = errno;
746                                                                 LOG_DEBUG("dup(STDOUT)=%d",
747                                                                         (int)semihosting->result);
748                                                         } else {
749                                                                 semihosting->result = dup(
750                                                                                 STDERR_FILENO);
751                                                                 semihosting->sys_errno = errno;
752                                                                 LOG_DEBUG("dup(STDERR)=%d",
753                                                                         (int)semihosting->result);
754                                                         }
755                                                 } else {
756                                                         /* cygwin requires the permission setting
757                                                          * otherwise it will fail to reopen a previously
758                                                          * written file */
759                                                         semihosting->result = open((char *)fn,
760                                                                         open_modeflags[mode],
761                                                                         0644);
762                                                         semihosting->sys_errno = errno;
763                                                         LOG_DEBUG("open('%s')=%d", fn,
764                                                                 (int)semihosting->result);
765                                                 }
766                                         }
767                                         free(fn);
768                                 }
769                         }
770                         break;
771
772                 case SEMIHOSTING_SYS_READ:      /* 0x06 */
773                         /*
774                          * Reads the contents of a file into a buffer. The file position
775                          * is specified either:
776                          * - Explicitly by a SYS_SEEK.
777                          * - Implicitly one byte beyond the previous SYS_READ or
778                          * SYS_WRITE request.
779                          *
780                          * The file position is at the start of the file when it is
781                          * opened, and is lost when the file is closed. Perform the
782                          * file operation as a single action whenever possible. For
783                          * example, do not split a read of 16KB into four 4KB chunks
784                          * unless there is no alternative.
785                          *
786                          * Entry
787                          * On entry, the PARAMETER REGISTER contains a pointer to a
788                          * three-field data block:
789                          * - field 1 Contains a handle for a file previously opened
790                          * with SYS_OPEN.
791                          * - field 2 Points to a buffer.
792                          * - field 3 Contains the number of bytes to read to the buffer
793                          * from the file.
794                          *
795                          * Return
796                          * On exit, the RETURN REGISTER contains the number of bytes not
797                          * filled in the buffer (buffer_length - bytes_read) as follows:
798                          * - If the RETURN REGISTER is 0, the entire buffer was
799                          * successfully filled.
800                          * - If the RETURN REGISTER is the same as field 3, no bytes
801                          * were read (EOF can be assumed).
802                          * - If the RETURN REGISTER contains a value smaller than
803                          * field 3, the read succeeded but the buffer was only partly
804                          * filled. For interactive devices, this is the most common
805                          * return value.
806                          */
807                         retval = semihosting_read_fields(target, 3, fields);
808                         if (retval != ERROR_OK)
809                                 return retval;
810                         else {
811                                 int fd = semihosting_get_field(target, 0, fields);
812                                 uint64_t addr = semihosting_get_field(target, 1, fields);
813                                 size_t len = semihosting_get_field(target, 2, fields);
814                                 if (semihosting->is_fileio) {
815                                         semihosting->hit_fileio = true;
816                                         fileio_info->identifier = "read";
817                                         fileio_info->param_1 = fd;
818                                         fileio_info->param_2 = addr;
819                                         fileio_info->param_3 = len;
820                                 } else {
821                                         uint8_t *buf = malloc(len);
822                                         if (!buf) {
823                                                 semihosting->result = -1;
824                                                 semihosting->sys_errno = ENOMEM;
825                                         } else {
826                                                 semihosting->result = read(fd, buf, len);
827                                                 semihosting->sys_errno = errno;
828                                                 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
829                                                         fd,
830                                                         addr,
831                                                         len,
832                                                         (int)semihosting->result);
833                                                 if (semihosting->result >= 0) {
834                                                         retval = target_write_buffer(target, addr,
835                                                                         semihosting->result,
836                                                                         buf);
837                                                         if (retval != ERROR_OK) {
838                                                                 free(buf);
839                                                                 return retval;
840                                                         }
841                                                         /* the number of bytes NOT filled in */
842                                                         semihosting->result = len -
843                                                                 semihosting->result;
844                                                 }
845                                                 free(buf);
846                                         }
847                                 }
848                         }
849                         break;
850
851                 case SEMIHOSTING_SYS_READC:     /* 0x07 */
852                         /*
853                          * Reads a byte from the console.
854                          *
855                          * Entry
856                          * The PARAMETER REGISTER must contain 0. There are no other
857                          * parameters or values possible.
858                          *
859                          * Return
860                          * On exit, the RETURN REGISTER contains the byte read from
861                          * the console.
862                          */
863                         if (semihosting->is_fileio) {
864                                 LOG_ERROR("SYS_READC not supported by semihosting fileio");
865                                 return ERROR_FAIL;
866                         }
867                         semihosting->result = getchar();
868                         LOG_DEBUG("getchar()=%d", (int)semihosting->result);
869                         break;
870
871                 case SEMIHOSTING_SYS_REMOVE:    /* 0x0E */
872                         /*
873                          * Deletes a specified file on the host filing system.
874                          *
875                          * Entry
876                          * On entry, the PARAMETER REGISTER contains a pointer to a
877                          * two-field argument block:
878                          * - field 1 Points to a null-terminated string that gives the
879                          * path name of the file to be deleted.
880                          * - field 2 The length of the string.
881                          *
882                          * Return
883                          * On exit, the RETURN REGISTER contains:
884                          * - 0 if the delete is successful
885                          * - A nonzero, host-specific error code if the delete fails.
886                          */
887                         retval = semihosting_read_fields(target, 2, fields);
888                         if (retval != ERROR_OK)
889                                 return retval;
890                         else {
891                                 uint64_t addr = semihosting_get_field(target, 0, fields);
892                                 size_t len = semihosting_get_field(target, 1, fields);
893                                 if (semihosting->is_fileio) {
894                                         semihosting->hit_fileio = true;
895                                         fileio_info->identifier = "unlink";
896                                         fileio_info->param_1 = addr;
897                                         fileio_info->param_2 = len;
898                                 } else {
899                                         uint8_t *fn = malloc(len+1);
900                                         if (!fn) {
901                                                 semihosting->result = -1;
902                                                 semihosting->sys_errno = ENOMEM;
903                                         } else {
904                                                 retval =
905                                                         target_read_memory(target, addr, 1, len,
906                                                                 fn);
907                                                 if (retval != ERROR_OK) {
908                                                         free(fn);
909                                                         return retval;
910                                                 }
911                                                 fn[len] = 0;
912                                                 semihosting->result = remove((char *)fn);
913                                                 semihosting->sys_errno = errno;
914                                                 LOG_DEBUG("remove('%s')=%d", fn,
915                                                         (int)semihosting->result);
916
917                                                 free(fn);
918                                         }
919                                 }
920                         }
921                         break;
922
923                 case SEMIHOSTING_SYS_RENAME:    /* 0x0F */
924                         /*
925                          * Renames a specified file.
926                          *
927                          * Entry
928                          * On entry, the PARAMETER REGISTER contains a pointer to a
929                          * four-field data block:
930                          * - field 1 A pointer to the name of the old file.
931                          * - field 2 The length of the old filename.
932                          * - field 3 A pointer to the new filename.
933                          * - field 4 The length of the new filename. Both strings are
934                          * null-terminated.
935                          *
936                          * Return
937                          * On exit, the RETURN REGISTER contains:
938                          * - 0 if the rename is successful.
939                          * - A nonzero, host-specific error code if the rename fails.
940                          */
941                         retval = semihosting_read_fields(target, 4, fields);
942                         if (retval != ERROR_OK)
943                                 return retval;
944                         else {
945                                 uint64_t addr1 = semihosting_get_field(target, 0, fields);
946                                 size_t len1 = semihosting_get_field(target, 1, fields);
947                                 uint64_t addr2 = semihosting_get_field(target, 2, fields);
948                                 size_t len2 = semihosting_get_field(target, 3, fields);
949                                 if (semihosting->is_fileio) {
950                                         semihosting->hit_fileio = true;
951                                         fileio_info->identifier = "rename";
952                                         fileio_info->param_1 = addr1;
953                                         fileio_info->param_2 = len1;
954                                         fileio_info->param_3 = addr2;
955                                         fileio_info->param_4 = len2;
956                                 } else {
957                                         uint8_t *fn1 = malloc(len1+1);
958                                         uint8_t *fn2 = malloc(len2+1);
959                                         if (!fn1 || !fn2) {
960                                                 free(fn1);
961                                                 free(fn2);
962                                                 semihosting->result = -1;
963                                                 semihosting->sys_errno = ENOMEM;
964                                         } else {
965                                                 retval = target_read_memory(target, addr1, 1, len1,
966                                                                 fn1);
967                                                 if (retval != ERROR_OK) {
968                                                         free(fn1);
969                                                         free(fn2);
970                                                         return retval;
971                                                 }
972                                                 retval = target_read_memory(target, addr2, 1, len2,
973                                                                 fn2);
974                                                 if (retval != ERROR_OK) {
975                                                         free(fn1);
976                                                         free(fn2);
977                                                         return retval;
978                                                 }
979                                                 fn1[len1] = 0;
980                                                 fn2[len2] = 0;
981                                                 semihosting->result = rename((char *)fn1,
982                                                                 (char *)fn2);
983                                                 semihosting->sys_errno = errno;
984                                                 LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2,
985                                                         (int)semihosting->result);
986
987                                                 free(fn1);
988                                                 free(fn2);
989                                         }
990                                 }
991                         }
992                         break;
993
994                 case SEMIHOSTING_SYS_SEEK:      /* 0x0A */
995                         /*
996                          * Seeks to a specified position in a file using an offset
997                          * specified from the start of the file. The file is assumed
998                          * to be a byte array and the offset is given in bytes.
999                          *
1000                          * Entry
1001                          * On entry, the PARAMETER REGISTER contains a pointer to a
1002                          * two-field data block:
1003                          * - field 1 A handle for a seekable file object.
1004                          * - field 2 The absolute byte position to seek to.
1005                          *
1006                          * Return
1007                          * On exit, the RETURN REGISTER contains:
1008                          * - 0 if the request is successful.
1009                          * - A negative value if the request is not successful.
1010                          * Use SYS_ERRNO to read the value of the host errno variable
1011                          * describing the error.
1012                          *
1013                          * Note: The effect of seeking outside the current extent of
1014                          * the file object is undefined.
1015                          */
1016                         retval = semihosting_read_fields(target, 2, fields);
1017                         if (retval != ERROR_OK)
1018                                 return retval;
1019                         else {
1020                                 int fd = semihosting_get_field(target, 0, fields);
1021                                 off_t pos = semihosting_get_field(target, 1, fields);
1022                                 if (semihosting->is_fileio) {
1023                                         semihosting->hit_fileio = true;
1024                                         fileio_info->identifier = "lseek";
1025                                         fileio_info->param_1 = fd;
1026                                         fileio_info->param_2 = pos;
1027                                         fileio_info->param_3 = SEEK_SET;
1028                                 } else {
1029                                         semihosting->result = lseek(fd, pos, SEEK_SET);
1030                                         semihosting->sys_errno = errno;
1031                                         LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos,
1032                                                 (int)semihosting->result);
1033                                         if (semihosting->result == pos)
1034                                                 semihosting->result = 0;
1035                                 }
1036                         }
1037                         break;
1038
1039                 case SEMIHOSTING_SYS_SYSTEM:    /* 0x12 */
1040                         /*
1041                          * Passes a command to the host command-line interpreter.
1042                          * This enables you to execute a system command such as dir,
1043                          * ls, or pwd. The terminal I/O is on the host, and is not
1044                          * visible to the target.
1045                          *
1046                          * Entry
1047                          * On entry, the PARAMETER REGISTER contains a pointer to a
1048                          * two-field argument block:
1049                          * - field 1 Points to a string to be passed to the host
1050                          * command-line interpreter.
1051                          * - field 2 The length of the string.
1052                          *
1053                          * Return
1054                          * On exit, the RETURN REGISTER contains the return status.
1055                          */
1056
1057                         /* Provide SYS_SYSTEM functionality.  Uses the
1058                          * libc system command, there may be a reason *NOT*
1059                          * to use this, but as I can't think of one, I
1060                          * implemented it this way.
1061                          */
1062                         retval = semihosting_read_fields(target, 2, fields);
1063                         if (retval != ERROR_OK)
1064                                 return retval;
1065                         else {
1066                                 uint64_t addr = semihosting_get_field(target, 0, fields);
1067                                 size_t len = semihosting_get_field(target, 1, fields);
1068                                 if (semihosting->is_fileio) {
1069                                         semihosting->hit_fileio = true;
1070                                         fileio_info->identifier = "system";
1071                                         fileio_info->param_1 = addr;
1072                                         fileio_info->param_2 = len;
1073                                 } else {
1074                                         uint8_t *cmd = malloc(len+1);
1075                                         if (!cmd) {
1076                                                 semihosting->result = -1;
1077                                                 semihosting->sys_errno = ENOMEM;
1078                                         } else {
1079                                                 retval = target_read_memory(target,
1080                                                                 addr,
1081                                                                 1,
1082                                                                 len,
1083                                                                 cmd);
1084                                                 if (retval != ERROR_OK) {
1085                                                         free(cmd);
1086                                                         return retval;
1087                                                 } else {
1088                                                         cmd[len] = 0;
1089                                                         semihosting->result = system(
1090                                                                         (const char *)cmd);
1091                                                         LOG_DEBUG("system('%s')=%d",
1092                                                                 cmd,
1093                                                                 (int)semihosting->result);
1094                                                 }
1095
1096                                                 free(cmd);
1097                                         }
1098                                 }
1099                         }
1100                         break;
1101
1102                 case SEMIHOSTING_SYS_TIME:      /* 0x11 */
1103                         /*
1104                          * Returns the number of seconds since 00:00 January 1, 1970.
1105                          * This value is real-world time, regardless of any debug agent
1106                          * configuration.
1107                          *
1108                          * Entry
1109                          * There are no parameters.
1110                          *
1111                          * Return
1112                          * On exit, the RETURN REGISTER contains the number of seconds.
1113                          */
1114                         semihosting->result = time(NULL);
1115                         break;
1116
1117                 case SEMIHOSTING_SYS_WRITE:     /* 0x05 */
1118                         /*
1119                          * Writes the contents of a buffer to a specified file at the
1120                          * current file position. The file position is specified either:
1121                          * - Explicitly, by a SYS_SEEK.
1122                          * - Implicitly as one byte beyond the previous SYS_READ or
1123                          * SYS_WRITE request.
1124                          *
1125                          * The file position is at the start of the file when the file
1126                          * is opened, and is lost when the file is closed.
1127                          *
1128                          * Perform the file operation as a single action whenever
1129                          * possible. For example, do not split a write of 16KB into
1130                          * four 4KB chunks unless there is no alternative.
1131                          *
1132                          * Entry
1133                          * On entry, the PARAMETER REGISTER contains a pointer to a
1134                          * three-field data block:
1135                          * - field 1 Contains a handle for a file previously opened
1136                          * with SYS_OPEN.
1137                          * - field 2 Points to the memory containing the data to be written.
1138                          * - field 3 Contains the number of bytes to be written from
1139                          * the buffer to the file.
1140                          *
1141                          * Return
1142                          * On exit, the RETURN REGISTER contains:
1143                          * - 0 if the call is successful.
1144                          * - The number of bytes that are not written, if there is an error.
1145                          */
1146                         retval = semihosting_read_fields(target, 3, fields);
1147                         if (retval != ERROR_OK)
1148                                 return retval;
1149                         else {
1150                                 int fd = semihosting_get_field(target, 0, fields);
1151                                 uint64_t addr = semihosting_get_field(target, 1, fields);
1152                                 size_t len = semihosting_get_field(target, 2, fields);
1153                                 if (semihosting->is_fileio) {
1154                                         semihosting->hit_fileio = true;
1155                                         fileio_info->identifier = "write";
1156                                         fileio_info->param_1 = fd;
1157                                         fileio_info->param_2 = addr;
1158                                         fileio_info->param_3 = len;
1159                                 } else {
1160                                         uint8_t *buf = malloc(len);
1161                                         if (!buf) {
1162                                                 semihosting->result = -1;
1163                                                 semihosting->sys_errno = ENOMEM;
1164                                         } else {
1165                                                 retval = target_read_buffer(target, addr, len, buf);
1166                                                 if (retval != ERROR_OK) {
1167                                                         free(buf);
1168                                                         return retval;
1169                                                 }
1170                                                 semihosting->result = write(fd, buf, len);
1171                                                 semihosting->sys_errno = errno;
1172                                                 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
1173                                                         fd,
1174                                                         addr,
1175                                                         len,
1176                                                         (int)semihosting->result);
1177                                                 if (semihosting->result >= 0) {
1178                                                         /* The number of bytes that are NOT written.
1179                                                          * */
1180                                                         semihosting->result = len -
1181                                                                 semihosting->result;
1182                                                 }
1183
1184                                                 free(buf);
1185                                         }
1186                                 }
1187                         }
1188                         break;
1189
1190                 case SEMIHOSTING_SYS_WRITEC:    /* 0x03 */
1191                         /*
1192                          * Writes a character byte, pointed to by the PARAMETER REGISTER,
1193                          * to the debug channel. When executed under a semihosting
1194                          * debugger, the character appears on the host debugger console.
1195                          *
1196                          * Entry
1197                          * On entry, the PARAMETER REGISTER contains a pointer to the
1198                          * character.
1199                          *
1200                          * Return
1201                          * None. The RETURN REGISTER is corrupted.
1202                          */
1203                         if (semihosting->is_fileio) {
1204                                 semihosting->hit_fileio = true;
1205                                 fileio_info->identifier = "write";
1206                                 fileio_info->param_1 = 1;
1207                                 fileio_info->param_2 = semihosting->param;
1208                                 fileio_info->param_3 = 1;
1209                         } else {
1210                                 uint64_t addr = semihosting->param;
1211                                 unsigned char c;
1212                                 retval = target_read_memory(target, addr, 1, 1, &c);
1213                                 if (retval != ERROR_OK)
1214                                         return retval;
1215                                 putchar(c);
1216                                 semihosting->result = 0;
1217                         }
1218                         break;
1219
1220                 case SEMIHOSTING_SYS_WRITE0:    /* 0x04 */
1221                         /*
1222                          * Writes a null-terminated string to the debug channel.
1223                          * When executed under a semihosting debugger, the characters
1224                          * appear on the host debugger console.
1225                          *
1226                          * Entry
1227                          * On entry, the PARAMETER REGISTER contains a pointer to the
1228                          * first byte of the string.
1229                          *
1230                          * Return
1231                          * None. The RETURN REGISTER is corrupted.
1232                          */
1233                         if (semihosting->is_fileio) {
1234                                 size_t count = 0;
1235                                 uint64_t addr = semihosting->param;
1236                                 for (;; addr++) {
1237                                         unsigned char c;
1238                                         retval = target_read_memory(target, addr, 1, 1, &c);
1239                                         if (retval != ERROR_OK)
1240                                                 return retval;
1241                                         if (c == '\0')
1242                                                 break;
1243                                         count++;
1244                                 }
1245                                 semihosting->hit_fileio = true;
1246                                 fileio_info->identifier = "write";
1247                                 fileio_info->param_1 = 1;
1248                                 fileio_info->param_2 = semihosting->param;
1249                                 fileio_info->param_3 = count;
1250                         } else {
1251                                 uint64_t addr = semihosting->param;
1252                                 do {
1253                                         unsigned char c;
1254                                         retval = target_read_memory(target, addr++, 1, 1, &c);
1255                                         if (retval != ERROR_OK)
1256                                                 return retval;
1257                                         if (!c)
1258                                                 break;
1259                                         putchar(c);
1260                                 } while (1);
1261                                 semihosting->result = 0;
1262                         }
1263                         break;
1264
1265                 case SEMIHOSTING_SYS_ELAPSED:   /* 0x30 */
1266                 /*
1267                  * Returns the number of elapsed target ticks since execution
1268                  * started.
1269                  * Use SYS_TICKFREQ to determine the tick frequency.
1270                  *
1271                  * Entry (32-bit)
1272                  * On entry, the PARAMETER REGISTER points to a two-field data
1273                  * block to be used for returning the number of elapsed ticks:
1274                  * - field 1 The least significant field and is at the low address.
1275                  * - field 2 The most significant field and is at the high address.
1276                  *
1277                  * Entry (64-bit)
1278                  * On entry the PARAMETER REGISTER points to a one-field data
1279                  * block to be used for returning the number of elapsed ticks:
1280                  * - field 1 The number of elapsed ticks as a 64-bit value.
1281                  *
1282                  * Return
1283                  * On exit:
1284                  * - On success, the RETURN REGISTER contains 0, the PARAMETER
1285                  * REGISTER is unchanged, and the data block pointed to by the
1286                  * PARAMETER REGISTER is filled in with the number of elapsed
1287                  * ticks.
1288                  * - On failure, the RETURN REGISTER contains -1, and the
1289                  * PARAMETER REGISTER contains -1.
1290                  *
1291                  * Note: Some semihosting implementations might not support this
1292                  * semihosting operation, and they always return -1 in the
1293                  * RETURN REGISTER.
1294                  */
1295
1296                 case SEMIHOSTING_SYS_TICKFREQ:  /* 0x31 */
1297                 /*
1298                  * Returns the tick frequency.
1299                  *
1300                  * Entry
1301                  * The PARAMETER REGISTER must contain 0 on entry to this routine.
1302                  *
1303                  * Return
1304                  * On exit, the RETURN REGISTER contains either:
1305                  * - The number of ticks per second.
1306                  * - –1 if the target does not know the value of one tick.
1307                  *
1308                  * Note: Some semihosting implementations might not support
1309                  * this semihosting operation, and they always return -1 in the
1310                  * RETURN REGISTER.
1311                  */
1312
1313                 case SEMIHOSTING_SYS_TMPNAM:    /* 0x0D */
1314                 /*
1315                  * Returns a temporary name for a file identified by a system
1316                  * file identifier.
1317                  *
1318                  * Entry
1319                  * On entry, the PARAMETER REGISTER contains a pointer to a
1320                  * three-word argument block:
1321                  * - field 1 A pointer to a buffer.
1322                  * - field 2 A target identifier for this filename. Its value
1323                  * must be an integer in the range 0-255.
1324                  * - field 3 Contains the length of the buffer. The length must
1325                  * be at least the value of L_tmpnam on the host system.
1326                  *
1327                  * Return
1328                  * On exit, the RETURN REGISTER contains:
1329                  * - 0 if the call is successful.
1330                  * - –1 if an error occurs.
1331                  *
1332                  * The buffer pointed to by the PARAMETER REGISTER contains
1333                  * the filename, prefixed with a suitable directory name.
1334                  * If you use the same target identifier again, the same
1335                  * filename is returned.
1336                  *
1337                  * Note: The returned string must be null-terminated.
1338                  */
1339
1340                 default:
1341                         fprintf(stderr, "semihosting: unsupported call %#x\n",
1342                                 (unsigned) semihosting->op);
1343                         semihosting->result = -1;
1344                         semihosting->sys_errno = ENOTSUP;
1345         }
1346
1347         if (!semihosting->hit_fileio) {
1348                 retval = semihosting->post_result(target);
1349                 if (retval != ERROR_OK) {
1350                         LOG_ERROR("Failed to post semihosting result");
1351                         return retval;
1352                 }
1353         }
1354
1355         return ERROR_OK;
1356 }
1357
1358 /* -------------------------------------------------------------------------
1359  * Local functions. */
1360
1361 static int semihosting_common_fileio_info(struct target *target,
1362         struct gdb_fileio_info *fileio_info)
1363 {
1364         struct semihosting *semihosting = target->semihosting;
1365         if (!semihosting)
1366                 return ERROR_FAIL;
1367
1368         /*
1369          * To avoid unnecessary duplication, semihosting prepares the
1370          * fileio_info structure out-of-band when the target halts. See
1371          * do_semihosting for more detail.
1372          */
1373         if (!semihosting->is_fileio || !semihosting->hit_fileio)
1374                 return ERROR_FAIL;
1375
1376         return ERROR_OK;
1377 }
1378
1379 static int semihosting_common_fileio_end(struct target *target, int result,
1380         int fileio_errno, bool ctrl_c)
1381 {
1382         struct gdb_fileio_info *fileio_info = target->fileio_info;
1383         struct semihosting *semihosting = target->semihosting;
1384         if (!semihosting)
1385                 return ERROR_FAIL;
1386
1387         /* clear pending status */
1388         semihosting->hit_fileio = false;
1389
1390         semihosting->result = result;
1391         semihosting->sys_errno = fileio_errno;
1392
1393         /*
1394          * Some fileio results do not match up with what the semihosting
1395          * operation expects; for these operations, we munge the results
1396          * below:
1397          */
1398         switch (semihosting->op) {
1399                 case SEMIHOSTING_SYS_WRITE:     /* 0x05 */
1400                         if (result < 0)
1401                                 semihosting->result = fileio_info->param_3;
1402                         else
1403                                 semihosting->result = 0;
1404                         break;
1405
1406                 case SEMIHOSTING_SYS_READ:      /* 0x06 */
1407                         if (result == (int)fileio_info->param_3)
1408                                 semihosting->result = 0;
1409                         if (result <= 0)
1410                                 semihosting->result = fileio_info->param_3;
1411                         break;
1412
1413                 case SEMIHOSTING_SYS_SEEK:      /* 0x0a */
1414                         if (result > 0)
1415                                 semihosting->result = 0;
1416                         break;
1417         }
1418
1419         return semihosting->post_result(target);
1420 }
1421
1422 /**
1423  * Read all fields of a command from target to buffer.
1424  */
1425 static int semihosting_read_fields(struct target *target, size_t number,
1426         uint8_t *fields)
1427 {
1428         struct semihosting *semihosting = target->semihosting;
1429         /* Use 4-byte multiples to trigger fast memory access. */
1430         return target_read_memory(target, semihosting->param, 4,
1431                         number * (semihosting->word_size_bytes / 4), fields);
1432 }
1433
1434 /**
1435  * Write all fields of a command from buffer to target.
1436  */
1437 static int semihosting_write_fields(struct target *target, size_t number,
1438         uint8_t *fields)
1439 {
1440         struct semihosting *semihosting = target->semihosting;
1441         /* Use 4-byte multiples to trigger fast memory access. */
1442         return target_write_memory(target, semihosting->param, 4,
1443                         number * (semihosting->word_size_bytes / 4), fields);
1444 }
1445
1446 /**
1447  * Extract a field from the buffer, considering register size and endianness.
1448  */
1449 static uint64_t semihosting_get_field(struct target *target, size_t index,
1450         uint8_t *fields)
1451 {
1452         struct semihosting *semihosting = target->semihosting;
1453         if (semihosting->word_size_bytes == 8)
1454                 return target_buffer_get_u64(target, fields + (index * 8));
1455         else
1456                 return target_buffer_get_u32(target, fields + (index * 4));
1457 }
1458
1459 /**
1460  * Store a field in the buffer, considering register size and endianness.
1461  */
1462 static void semihosting_set_field(struct target *target, uint64_t value,
1463         size_t index,
1464         uint8_t *fields)
1465 {
1466         struct semihosting *semihosting = target->semihosting;
1467         if (semihosting->word_size_bytes == 8)
1468                 target_buffer_set_u64(target, fields + (index * 8), value);
1469         else
1470                 target_buffer_set_u32(target, fields + (index * 4), value);
1471 }
1472
1473
1474 /* -------------------------------------------------------------------------
1475  * Common semihosting commands handlers. */
1476
1477 static __COMMAND_HANDLER(handle_common_semihosting_command)
1478 {
1479         struct target *target = get_current_target(CMD_CTX);
1480
1481         if (target == NULL) {
1482                 LOG_ERROR("No target selected");
1483                 return ERROR_FAIL;
1484         }
1485
1486         struct semihosting *semihosting = target->semihosting;
1487         if (!semihosting) {
1488                 command_print(CMD, "semihosting not supported for current target");
1489                 return ERROR_FAIL;
1490         }
1491
1492         if (CMD_ARGC > 0) {
1493                 int is_active;
1494
1495                 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1496
1497                 if (!target_was_examined(target)) {
1498                         LOG_ERROR("Target not examined yet");
1499                         return ERROR_FAIL;
1500                 }
1501
1502                 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1503                         LOG_ERROR("Failed to Configure semihosting");
1504                         return ERROR_FAIL;
1505                 }
1506
1507                 /* FIXME never let that "catch" be dropped! (???) */
1508                 semihosting->is_active = is_active;
1509         }
1510
1511         command_print(CMD, "semihosting is %s",
1512                 semihosting->is_active
1513                 ? "enabled" : "disabled");
1514
1515         return ERROR_OK;
1516 }
1517
1518 static __COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1519 {
1520         struct target *target = get_current_target(CMD_CTX);
1521
1522         if (target == NULL) {
1523                 LOG_ERROR("No target selected");
1524                 return ERROR_FAIL;
1525         }
1526
1527         struct semihosting *semihosting = target->semihosting;
1528         if (!semihosting) {
1529                 command_print(CMD, "semihosting not supported for current target");
1530                 return ERROR_FAIL;
1531         }
1532
1533         if (!semihosting->is_active) {
1534                 command_print(CMD, "semihosting not yet enabled for current target");
1535                 return ERROR_FAIL;
1536         }
1537
1538         if (CMD_ARGC > 0)
1539                 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1540
1541         command_print(CMD, "semihosting fileio is %s",
1542                 semihosting->is_fileio
1543                 ? "enabled" : "disabled");
1544
1545         return ERROR_OK;
1546 }
1547
1548 static __COMMAND_HANDLER(handle_common_semihosting_cmdline)
1549 {
1550         struct target *target = get_current_target(CMD_CTX);
1551         unsigned int i;
1552
1553         if (target == NULL) {
1554                 LOG_ERROR("No target selected");
1555                 return ERROR_FAIL;
1556         }
1557
1558         struct semihosting *semihosting = target->semihosting;
1559         if (!semihosting) {
1560                 command_print(CMD, "semihosting not supported for current target");
1561                 return ERROR_FAIL;
1562         }
1563
1564         free(semihosting->cmdline);
1565         semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
1566
1567         for (i = 1; i < CMD_ARGC; i++) {
1568                 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
1569                 if (cmdline == NULL)
1570                         break;
1571                 free(semihosting->cmdline);
1572                 semihosting->cmdline = cmdline;
1573         }
1574
1575         command_print(CMD, "semihosting command line is [%s]",
1576                 semihosting->cmdline);
1577
1578         return ERROR_OK;
1579 }
1580
1581 static __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
1582 {
1583         struct target *target = get_current_target(CMD_CTX);
1584
1585         if (target == NULL) {
1586                 LOG_ERROR("No target selected");
1587                 return ERROR_FAIL;
1588         }
1589
1590         struct semihosting *semihosting = target->semihosting;
1591         if (!semihosting) {
1592                 command_print(CMD, "semihosting not supported for current target");
1593                 return ERROR_FAIL;
1594         }
1595
1596         if (!semihosting->is_active) {
1597                 command_print(CMD, "semihosting not yet enabled for current target");
1598                 return ERROR_FAIL;
1599         }
1600
1601         if (CMD_ARGC > 0)
1602                 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
1603
1604         command_print(CMD, "semihosting resumable exit is %s",
1605                 semihosting->has_resumable_exit
1606                 ? "enabled" : "disabled");
1607
1608         return ERROR_OK;
1609 }
1610
1611 const struct command_registration semihosting_common_handlers[] = {
1612         {
1613                 "semihosting",
1614                 .handler = handle_common_semihosting_command,
1615                 .mode = COMMAND_EXEC,
1616                 .usage = "['enable'|'disable']",
1617                 .help = "activate support for semihosting operations",
1618         },
1619         {
1620                 "semihosting_cmdline",
1621                 .handler = handle_common_semihosting_cmdline,
1622                 .mode = COMMAND_EXEC,
1623                 .usage = "arguments",
1624                 .help = "command line arguments to be passed to program",
1625         },
1626         {
1627                 "semihosting_fileio",
1628                 .handler = handle_common_semihosting_fileio_command,
1629                 .mode = COMMAND_EXEC,
1630                 .usage = "['enable'|'disable']",
1631                 .help = "activate support for semihosting fileio operations",
1632         },
1633         {
1634                 "semihosting_resexit",
1635                 .handler = handle_common_semihosting_resumable_exit_command,
1636                 .mode = COMMAND_EXEC,
1637                 .usage = "['enable'|'disable']",
1638                 .help = "activate support for semihosting resumable exit",
1639         },
1640         COMMAND_REGISTRATION_DONE
1641 };