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