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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)