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