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