2df6e38aeaadbfd10dceb847770b06ff82a17004
[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 strncpy((char *)fn, semihosting->basedir, basedir_len);
881 if (fn[basedir_len - 1] != '/')
882 fn[basedir_len++] = '/';
883 retval = target_read_memory(target, addr, 1, len, fn + basedir_len);
884 if (retval != ERROR_OK) {
885 free(fn);
886 return retval;
887 }
888 fn[basedir_len + len] = 0;
889 /* TODO: implement the :semihosting-features special file.
890 * */
891 if (semihosting->is_fileio) {
892 if (strcmp((char *)fn, ":semihosting-features") == 0) {
893 semihosting->result = -1;
894 semihosting->sys_errno = EINVAL;
895 } else if (strcmp((char *)fn, ":tt") == 0) {
896 if (mode == 0)
897 semihosting->result = 0;
898 else if (mode == 4)
899 semihosting->result = 1;
900 else if (mode == 8)
901 semihosting->result = 2;
902 else
903 semihosting->result = -1;
904 } else {
905 semihosting->hit_fileio = true;
906 fileio_info->identifier = "open";
907 fileio_info->param_1 = addr;
908 fileio_info->param_2 = len;
909 fileio_info->param_3 = open_gdb_modeflags[mode];
910 fileio_info->param_4 = 0644;
911 }
912 } else {
913 if (strcmp((char *)fn, ":tt") == 0) {
914 /* Mode is:
915 * - 0-3 ("r") for stdin,
916 * - 4-7 ("w") for stdout,
917 * - 8-11 ("a") for stderr */
918 if (mode < 4) {
919 int fd = dup(STDIN_FILENO);
920 semihosting->result = fd;
921 semihosting->stdin_fd = fd;
922 semihosting->sys_errno = errno;
923 LOG_DEBUG("dup(STDIN)=%d",
924 (int)semihosting->result);
925 } else if (mode < 8) {
926 int fd = dup(STDOUT_FILENO);
927 semihosting->result = fd;
928 semihosting->stdout_fd = fd;
929 semihosting->sys_errno = errno;
930 LOG_DEBUG("dup(STDOUT)=%d",
931 (int)semihosting->result);
932 } else {
933 int fd = dup(STDERR_FILENO);
934 semihosting->result = fd;
935 semihosting->stderr_fd = fd;
936 semihosting->sys_errno = errno;
937 LOG_DEBUG("dup(STDERR)=%d",
938 (int)semihosting->result);
939 }
940 } else {
941 /* cygwin requires the permission setting
942 * otherwise it will fail to reopen a previously
943 * written file */
944 semihosting->result = open((char *)fn,
945 open_host_modeflags[mode],
946 0644);
947 semihosting->sys_errno = errno;
948 LOG_DEBUG("open('%s')=%d", fn,
949 (int)semihosting->result);
950 }
951 }
952 free(fn);
953 }
954 }
955 break;
956
957 case SEMIHOSTING_SYS_READ: /* 0x06 */
958 /*
959 * Reads the contents of a file into a buffer. The file position
960 * is specified either:
961 * - Explicitly by a SYS_SEEK.
962 * - Implicitly one byte beyond the previous SYS_READ or
963 * SYS_WRITE request.
964 *
965 * The file position is at the start of the file when it is
966 * opened, and is lost when the file is closed. Perform the
967 * file operation as a single action whenever possible. For
968 * example, do not split a read of 16KB into four 4KB chunks
969 * unless there is no alternative.
970 *
971 * Entry
972 * On entry, the PARAMETER REGISTER contains a pointer to a
973 * three-field data block:
974 * - field 1 Contains a handle for a file previously opened
975 * with SYS_OPEN.
976 * - field 2 Points to a buffer.
977 * - field 3 Contains the number of bytes to read to the buffer
978 * from the file.
979 *
980 * Return
981 * On exit, the RETURN REGISTER contains the number of bytes not
982 * filled in the buffer (buffer_length - bytes_read) as follows:
983 * - If the RETURN REGISTER is 0, the entire buffer was
984 * successfully filled.
985 * - If the RETURN REGISTER is the same as field 3, no bytes
986 * were read (EOF can be assumed).
987 * - If the RETURN REGISTER contains a value smaller than
988 * field 3, the read succeeded but the buffer was only partly
989 * filled. For interactive devices, this is the most common
990 * return value.
991 */
992 retval = semihosting_read_fields(target, 3, fields);
993 if (retval != ERROR_OK)
994 return retval;
995 else {
996 int fd = semihosting_get_field(target, 0, fields);
997 uint64_t addr = semihosting_get_field(target, 1, fields);
998 size_t len = semihosting_get_field(target, 2, fields);
999 if (semihosting->is_fileio) {
1000 semihosting->hit_fileio = true;
1001 fileio_info->identifier = "read";
1002 fileio_info->param_1 = fd;
1003 fileio_info->param_2 = addr;
1004 fileio_info->param_3 = len;
1005 } else {
1006 uint8_t *buf = malloc(len);
1007 if (!buf) {
1008 semihosting->result = -1;
1009 semihosting->sys_errno = ENOMEM;
1010 } else {
1011 semihosting->result = semihosting_read(semihosting, fd, buf, len);
1012 LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d",
1013 fd,
1014 addr,
1015 len,
1016 (int)semihosting->result);
1017 if (semihosting->result >= 0) {
1018 retval = target_write_buffer(target, addr,
1019 semihosting->result,
1020 buf);
1021 if (retval != ERROR_OK) {
1022 free(buf);
1023 return retval;
1024 }
1025 /* the number of bytes NOT filled in */
1026 semihosting->result = len -
1027 semihosting->result;
1028 }
1029 free(buf);
1030 }
1031 }
1032 }
1033 break;
1034
1035 case SEMIHOSTING_SYS_READC: /* 0x07 */
1036 /*
1037 * Reads a byte from the console.
1038 *
1039 * Entry
1040 * The PARAMETER REGISTER must contain 0. There are no other
1041 * parameters or values possible.
1042 *
1043 * Return
1044 * On exit, the RETURN REGISTER contains the byte read from
1045 * the console.
1046 */
1047 if (semihosting->is_fileio) {
1048 LOG_ERROR("SYS_READC not supported by semihosting fileio");
1049 return ERROR_FAIL;
1050 }
1051 semihosting->result = semihosting_getchar(semihosting, semihosting->stdin_fd);
1052 LOG_DEBUG("getchar()=%d", (int)semihosting->result);
1053 break;
1054
1055 case SEMIHOSTING_SYS_REMOVE: /* 0x0E */
1056 /*
1057 * Deletes a specified file on the host filing system.
1058 *
1059 * Entry
1060 * On entry, the PARAMETER REGISTER contains a pointer to a
1061 * two-field argument block:
1062 * - field 1 Points to a null-terminated string that gives the
1063 * path name of the file to be deleted.
1064 * - field 2 The length of the string.
1065 *
1066 * Return
1067 * On exit, the RETURN REGISTER contains:
1068 * - 0 if the delete is successful
1069 * - A nonzero, host-specific error code if the delete fails.
1070 */
1071 retval = semihosting_read_fields(target, 2, fields);
1072 if (retval != ERROR_OK)
1073 return retval;
1074 else {
1075 uint64_t addr = semihosting_get_field(target, 0, fields);
1076 size_t len = semihosting_get_field(target, 1, fields);
1077 if (semihosting->is_fileio) {
1078 semihosting->hit_fileio = true;
1079 fileio_info->identifier = "unlink";
1080 fileio_info->param_1 = addr;
1081 fileio_info->param_2 = len;
1082 } else {
1083 uint8_t *fn = malloc(len+1);
1084 if (!fn) {
1085 semihosting->result = -1;
1086 semihosting->sys_errno = ENOMEM;
1087 } else {
1088 retval =
1089 target_read_memory(target, addr, 1, len,
1090 fn);
1091 if (retval != ERROR_OK) {
1092 free(fn);
1093 return retval;
1094 }
1095 fn[len] = 0;
1096 semihosting->result = remove((char *)fn);
1097 semihosting->sys_errno = errno;
1098 LOG_DEBUG("remove('%s')=%d", fn,
1099 (int)semihosting->result);
1100
1101 free(fn);
1102 }
1103 }
1104 }
1105 break;
1106
1107 case SEMIHOSTING_SYS_RENAME: /* 0x0F */
1108 /*
1109 * Renames a specified file.
1110 *
1111 * Entry
1112 * On entry, the PARAMETER REGISTER contains a pointer to a
1113 * four-field data block:
1114 * - field 1 A pointer to the name of the old file.
1115 * - field 2 The length of the old filename.
1116 * - field 3 A pointer to the new filename.
1117 * - field 4 The length of the new filename. Both strings are
1118 * null-terminated.
1119 *
1120 * Return
1121 * On exit, the RETURN REGISTER contains:
1122 * - 0 if the rename is successful.
1123 * - A nonzero, host-specific error code if the rename fails.
1124 */
1125 retval = semihosting_read_fields(target, 4, fields);
1126 if (retval != ERROR_OK)
1127 return retval;
1128 else {
1129 uint64_t addr1 = semihosting_get_field(target, 0, fields);
1130 size_t len1 = semihosting_get_field(target, 1, fields);
1131 uint64_t addr2 = semihosting_get_field(target, 2, fields);
1132 size_t len2 = semihosting_get_field(target, 3, fields);
1133 if (semihosting->is_fileio) {
1134 semihosting->hit_fileio = true;
1135 fileio_info->identifier = "rename";
1136 fileio_info->param_1 = addr1;
1137 fileio_info->param_2 = len1;
1138 fileio_info->param_3 = addr2;
1139 fileio_info->param_4 = len2;
1140 } else {
1141 uint8_t *fn1 = malloc(len1+1);
1142 uint8_t *fn2 = malloc(len2+1);
1143 if (!fn1 || !fn2) {
1144 free(fn1);
1145 free(fn2);
1146 semihosting->result = -1;
1147 semihosting->sys_errno = ENOMEM;
1148 } else {
1149 retval = target_read_memory(target, addr1, 1, len1,
1150 fn1);
1151 if (retval != ERROR_OK) {
1152 free(fn1);
1153 free(fn2);
1154 return retval;
1155 }
1156 retval = target_read_memory(target, addr2, 1, len2,
1157 fn2);
1158 if (retval != ERROR_OK) {
1159 free(fn1);
1160 free(fn2);
1161 return retval;
1162 }
1163 fn1[len1] = 0;
1164 fn2[len2] = 0;
1165 semihosting->result = rename((char *)fn1,
1166 (char *)fn2);
1167 semihosting->sys_errno = errno;
1168 LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2,
1169 (int)semihosting->result);
1170
1171 free(fn1);
1172 free(fn2);
1173 }
1174 }
1175 }
1176 break;
1177
1178 case SEMIHOSTING_SYS_SEEK: /* 0x0A */
1179 /*
1180 * Seeks to a specified position in a file using an offset
1181 * specified from the start of the file. The file is assumed
1182 * to be a byte array and the offset is given in bytes.
1183 *
1184 * Entry
1185 * On entry, the PARAMETER REGISTER contains a pointer to a
1186 * two-field data block:
1187 * - field 1 A handle for a seekable file object.
1188 * - field 2 The absolute byte position to seek to.
1189 *
1190 * Return
1191 * On exit, the RETURN REGISTER contains:
1192 * - 0 if the request is successful.
1193 * - A negative value if the request is not successful.
1194 * Use SYS_ERRNO to read the value of the host errno variable
1195 * describing the error.
1196 *
1197 * Note: The effect of seeking outside the current extent of
1198 * the file object is undefined.
1199 */
1200 retval = semihosting_read_fields(target, 2, fields);
1201 if (retval != ERROR_OK)
1202 return retval;
1203 else {
1204 int fd = semihosting_get_field(target, 0, fields);
1205 off_t pos = semihosting_get_field(target, 1, fields);
1206 if (semihosting->is_fileio) {
1207 semihosting->hit_fileio = true;
1208 fileio_info->identifier = "lseek";
1209 fileio_info->param_1 = fd;
1210 fileio_info->param_2 = pos;
1211 fileio_info->param_3 = SEEK_SET;
1212 } else {
1213 semihosting->result = lseek(fd, pos, SEEK_SET);
1214 semihosting->sys_errno = errno;
1215 LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos,
1216 (int)semihosting->result);
1217 if (semihosting->result == pos)
1218 semihosting->result = 0;
1219 }
1220 }
1221 break;
1222
1223 case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */
1224 /*
1225 * Passes a command to the host command-line interpreter.
1226 * This enables you to execute a system command such as dir,
1227 * ls, or pwd. The terminal I/O is on the host, and is not
1228 * visible to the target.
1229 *
1230 * Entry
1231 * On entry, the PARAMETER REGISTER contains a pointer to a
1232 * two-field argument block:
1233 * - field 1 Points to a string to be passed to the host
1234 * command-line interpreter.
1235 * - field 2 The length of the string.
1236 *
1237 * Return
1238 * On exit, the RETURN REGISTER contains the return status.
1239 */
1240
1241 /* Provide SYS_SYSTEM functionality. Uses the
1242 * libc system command, there may be a reason *NOT*
1243 * to use this, but as I can't think of one, I
1244 * implemented it this way.
1245 */
1246 retval = semihosting_read_fields(target, 2, fields);
1247 if (retval != ERROR_OK)
1248 return retval;
1249 else {
1250 uint64_t addr = semihosting_get_field(target, 0, fields);
1251 size_t len = semihosting_get_field(target, 1, fields);
1252 if (semihosting->is_fileio) {
1253 semihosting->hit_fileio = true;
1254 fileio_info->identifier = "system";
1255 fileio_info->param_1 = addr;
1256 fileio_info->param_2 = len;
1257 } else {
1258 uint8_t *cmd = malloc(len+1);
1259 if (!cmd) {
1260 semihosting->result = -1;
1261 semihosting->sys_errno = ENOMEM;
1262 } else {
1263 retval = target_read_memory(target,
1264 addr,
1265 1,
1266 len,
1267 cmd);
1268 if (retval != ERROR_OK) {
1269 free(cmd);
1270 return retval;
1271 } else {
1272 cmd[len] = 0;
1273 semihosting->result = system(
1274 (const char *)cmd);
1275 LOG_DEBUG("system('%s')=%d",
1276 cmd,
1277 (int)semihosting->result);
1278 }
1279
1280 free(cmd);
1281 }
1282 }
1283 }
1284 break;
1285
1286 case SEMIHOSTING_SYS_TIME: /* 0x11 */
1287 /*
1288 * Returns the number of seconds since 00:00 January 1, 1970.
1289 * This value is real-world time, regardless of any debug agent
1290 * configuration.
1291 *
1292 * Entry
1293 * There are no parameters.
1294 *
1295 * Return
1296 * On exit, the RETURN REGISTER contains the number of seconds.
1297 */
1298 semihosting->result = time(NULL);
1299 break;
1300
1301 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1302 /*
1303 * Writes the contents of a buffer to a specified file at the
1304 * current file position. The file position is specified either:
1305 * - Explicitly, by a SYS_SEEK.
1306 * - Implicitly as one byte beyond the previous SYS_READ or
1307 * SYS_WRITE request.
1308 *
1309 * The file position is at the start of the file when the file
1310 * is opened, and is lost when the file is closed.
1311 *
1312 * Perform the file operation as a single action whenever
1313 * possible. For example, do not split a write of 16KB into
1314 * four 4KB chunks unless there is no alternative.
1315 *
1316 * Entry
1317 * On entry, the PARAMETER REGISTER contains a pointer to a
1318 * three-field data block:
1319 * - field 1 Contains a handle for a file previously opened
1320 * with SYS_OPEN.
1321 * - field 2 Points to the memory containing the data to be written.
1322 * - field 3 Contains the number of bytes to be written from
1323 * the buffer to the file.
1324 *
1325 * Return
1326 * On exit, the RETURN REGISTER contains:
1327 * - 0 if the call is successful.
1328 * - The number of bytes that are not written, if there is an error.
1329 */
1330 retval = semihosting_read_fields(target, 3, fields);
1331 if (retval != ERROR_OK)
1332 return retval;
1333 else {
1334 int fd = semihosting_get_field(target, 0, fields);
1335 uint64_t addr = semihosting_get_field(target, 1, fields);
1336 size_t len = semihosting_get_field(target, 2, fields);
1337 if (semihosting->is_fileio) {
1338 semihosting->hit_fileio = true;
1339 fileio_info->identifier = "write";
1340 fileio_info->param_1 = fd;
1341 fileio_info->param_2 = addr;
1342 fileio_info->param_3 = len;
1343 } else {
1344 uint8_t *buf = malloc(len);
1345 if (!buf) {
1346 semihosting->result = -1;
1347 semihosting->sys_errno = ENOMEM;
1348 } else {
1349 retval = target_read_buffer(target, addr, len, buf);
1350 if (retval != ERROR_OK) {
1351 free(buf);
1352 return retval;
1353 }
1354 semihosting->result = semihosting_write(semihosting, fd, buf, len);
1355 semihosting->sys_errno = errno;
1356 LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d",
1357 fd,
1358 addr,
1359 len,
1360 (int)semihosting->result);
1361 if (semihosting->result >= 0) {
1362 /* The number of bytes that are NOT written.
1363 * */
1364 semihosting->result = len -
1365 semihosting->result;
1366 }
1367
1368 free(buf);
1369 }
1370 }
1371 }
1372 break;
1373
1374 case SEMIHOSTING_SYS_WRITEC: /* 0x03 */
1375 /*
1376 * Writes a character byte, pointed to by the PARAMETER REGISTER,
1377 * to the debug channel. When executed under a semihosting
1378 * debugger, the character appears on the host debugger console.
1379 *
1380 * Entry
1381 * On entry, the PARAMETER REGISTER contains a pointer to the
1382 * character.
1383 *
1384 * Return
1385 * None. The RETURN REGISTER is corrupted.
1386 */
1387 if (semihosting->is_fileio) {
1388 semihosting->hit_fileio = true;
1389 fileio_info->identifier = "write";
1390 fileio_info->param_1 = 1;
1391 fileio_info->param_2 = semihosting->param;
1392 fileio_info->param_3 = 1;
1393 } else {
1394 uint64_t addr = semihosting->param;
1395 unsigned char c;
1396 retval = target_read_memory(target, addr, 1, 1, &c);
1397 if (retval != ERROR_OK)
1398 return retval;
1399 semihosting_putchar(semihosting, semihosting->stdout_fd, c);
1400 semihosting->result = 0;
1401 }
1402 break;
1403
1404 case SEMIHOSTING_SYS_WRITE0: /* 0x04 */
1405 /*
1406 * Writes a null-terminated string to the debug channel.
1407 * When executed under a semihosting debugger, the characters
1408 * appear on the host debugger console.
1409 *
1410 * Entry
1411 * On entry, the PARAMETER REGISTER contains a pointer to the
1412 * first byte of the string.
1413 *
1414 * Return
1415 * None. The RETURN REGISTER is corrupted.
1416 */
1417 if (semihosting->is_fileio) {
1418 size_t count = 0;
1419 uint64_t addr = semihosting->param;
1420 for (;; addr++) {
1421 unsigned char c;
1422 retval = target_read_memory(target, addr, 1, 1, &c);
1423 if (retval != ERROR_OK)
1424 return retval;
1425 if (c == '\0')
1426 break;
1427 count++;
1428 }
1429 semihosting->hit_fileio = true;
1430 fileio_info->identifier = "write";
1431 fileio_info->param_1 = 1;
1432 fileio_info->param_2 = semihosting->param;
1433 fileio_info->param_3 = count;
1434 } else {
1435 uint64_t addr = semihosting->param;
1436 do {
1437 unsigned char c;
1438 retval = target_read_memory(target, addr++, 1, 1, &c);
1439 if (retval != ERROR_OK)
1440 return retval;
1441 if (!c)
1442 break;
1443 semihosting_putchar(semihosting, semihosting->stdout_fd, c);
1444 } while (1);
1445 semihosting->result = 0;
1446 }
1447 break;
1448
1449 case SEMIHOSTING_USER_CMD_0x100 ... SEMIHOSTING_USER_CMD_0x107:
1450 /**
1451 * This is a user defined operation (while user cmds 0x100-0x1ff
1452 * are possible, only 0x100-0x107 are currently implemented).
1453 *
1454 * Reads the user operation parameters from target, then fires the
1455 * corresponding target event. When the target callbacks returned,
1456 * cleans up the command parameter buffer.
1457 *
1458 * Entry
1459 * On entry, the PARAMETER REGISTER contains a pointer to a
1460 * two-field data block:
1461 * - field 1 Contains a pointer to the bound command parameter
1462 * string
1463 * - field 2 Contains the command parameter string length
1464 *
1465 * Return
1466 * On exit, the RETURN REGISTER contains the return status.
1467 */
1468 {
1469 assert(!semihosting_user_op_params);
1470
1471 retval = semihosting_read_fields(target, 2, fields);
1472 if (retval != ERROR_OK) {
1473 LOG_ERROR("Failed to read fields for user defined command"
1474 " op=0x%x", semihosting->op);
1475 return retval;
1476 }
1477
1478 uint64_t addr = semihosting_get_field(target, 0, fields);
1479
1480 size_t len = semihosting_get_field(target, 1, fields);
1481 if (len > SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH) {
1482 LOG_ERROR("The maximum length for user defined command "
1483 "parameter is %u, received length is %zu (op=0x%x)",
1484 SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH,
1485 len,
1486 semihosting->op);
1487 return ERROR_FAIL;
1488 }
1489
1490 semihosting_user_op_params = malloc(len + 1);
1491 if (!semihosting_user_op_params)
1492 return ERROR_FAIL;
1493 semihosting_user_op_params[len] = 0;
1494
1495 retval = target_read_buffer(target, addr, len,
1496 (uint8_t *)(semihosting_user_op_params));
1497 if (retval != ERROR_OK) {
1498 LOG_ERROR("Failed to read from target, semihosting op=0x%x",
1499 semihosting->op);
1500 free(semihosting_user_op_params);
1501 semihosting_user_op_params = NULL;
1502 return retval;
1503 }
1504
1505 target_handle_event(target, semihosting->op);
1506 free(semihosting_user_op_params);
1507 semihosting_user_op_params = NULL;
1508
1509 semihosting->result = 0;
1510 break;
1511 }
1512
1513
1514 case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */
1515 /*
1516 * Returns the number of elapsed target ticks since execution
1517 * started.
1518 * Use SYS_TICKFREQ to determine the tick frequency.
1519 *
1520 * Entry (32-bit)
1521 * On entry, the PARAMETER REGISTER points to a two-field data
1522 * block to be used for returning the number of elapsed ticks:
1523 * - field 1 The least significant field and is at the low address.
1524 * - field 2 The most significant field and is at the high address.
1525 *
1526 * Entry (64-bit)
1527 * On entry the PARAMETER REGISTER points to a one-field data
1528 * block to be used for returning the number of elapsed ticks:
1529 * - field 1 The number of elapsed ticks as a 64-bit value.
1530 *
1531 * Return
1532 * On exit:
1533 * - On success, the RETURN REGISTER contains 0, the PARAMETER
1534 * REGISTER is unchanged, and the data block pointed to by the
1535 * PARAMETER REGISTER is filled in with the number of elapsed
1536 * ticks.
1537 * - On failure, the RETURN REGISTER contains -1, and the
1538 * PARAMETER REGISTER contains -1.
1539 *
1540 * Note: Some semihosting implementations might not support this
1541 * semihosting operation, and they always return -1 in the
1542 * RETURN REGISTER.
1543 */
1544
1545 case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */
1546 /*
1547 * Returns the tick frequency.
1548 *
1549 * Entry
1550 * The PARAMETER REGISTER must contain 0 on entry to this routine.
1551 *
1552 * Return
1553 * On exit, the RETURN REGISTER contains either:
1554 * - The number of ticks per second.
1555 * - –1 if the target does not know the value of one tick.
1556 *
1557 * Note: Some semihosting implementations might not support
1558 * this semihosting operation, and they always return -1 in the
1559 * RETURN REGISTER.
1560 */
1561
1562 case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */
1563 /*
1564 * Returns a temporary name for a file identified by a system
1565 * file identifier.
1566 *
1567 * Entry
1568 * On entry, the PARAMETER REGISTER contains a pointer to a
1569 * three-word argument block:
1570 * - field 1 A pointer to a buffer.
1571 * - field 2 A target identifier for this filename. Its value
1572 * must be an integer in the range 0-255.
1573 * - field 3 Contains the length of the buffer. The length must
1574 * be at least the value of L_tmpnam on the host system.
1575 *
1576 * Return
1577 * On exit, the RETURN REGISTER contains:
1578 * - 0 if the call is successful.
1579 * - –1 if an error occurs.
1580 *
1581 * The buffer pointed to by the PARAMETER REGISTER contains
1582 * the filename, prefixed with a suitable directory name.
1583 * If you use the same target identifier again, the same
1584 * filename is returned.
1585 *
1586 * Note: The returned string must be null-terminated.
1587 */
1588
1589 default:
1590 fprintf(stderr, "semihosting: unsupported call %#x\n",
1591 (unsigned) semihosting->op);
1592 semihosting->result = -1;
1593 semihosting->sys_errno = ENOTSUP;
1594 }
1595
1596 if (!semihosting->hit_fileio) {
1597 retval = semihosting->post_result(target);
1598 if (retval != ERROR_OK) {
1599 LOG_ERROR("Failed to post semihosting result");
1600 return retval;
1601 }
1602 }
1603
1604 return ERROR_OK;
1605 }
1606
1607 /* -------------------------------------------------------------------------
1608 * Local functions. */
1609
1610 static int semihosting_common_fileio_info(struct target *target,
1611 struct gdb_fileio_info *fileio_info)
1612 {
1613 struct semihosting *semihosting = target->semihosting;
1614 if (!semihosting)
1615 return ERROR_FAIL;
1616
1617 /*
1618 * To avoid unnecessary duplication, semihosting prepares the
1619 * fileio_info structure out-of-band when the target halts. See
1620 * do_semihosting for more detail.
1621 */
1622 if (!semihosting->is_fileio || !semihosting->hit_fileio)
1623 return ERROR_FAIL;
1624
1625 return ERROR_OK;
1626 }
1627
1628 static int semihosting_common_fileio_end(struct target *target, int result,
1629 int fileio_errno, bool ctrl_c)
1630 {
1631 struct gdb_fileio_info *fileio_info = target->fileio_info;
1632 struct semihosting *semihosting = target->semihosting;
1633 if (!semihosting)
1634 return ERROR_FAIL;
1635
1636 /* clear pending status */
1637 semihosting->hit_fileio = false;
1638
1639 semihosting->result = result;
1640 semihosting->sys_errno = fileio_errno;
1641
1642 /*
1643 * Some fileio results do not match up with what the semihosting
1644 * operation expects; for these operations, we munge the results
1645 * below:
1646 */
1647 switch (semihosting->op) {
1648 case SEMIHOSTING_SYS_WRITE: /* 0x05 */
1649 if (result < 0)
1650 semihosting->result = fileio_info->param_3;
1651 else
1652 semihosting->result = 0;
1653 break;
1654
1655 case SEMIHOSTING_SYS_READ: /* 0x06 */
1656 if (result == (int)fileio_info->param_3)
1657 semihosting->result = 0;
1658 if (result <= 0)
1659 semihosting->result = fileio_info->param_3;
1660 break;
1661
1662 case SEMIHOSTING_SYS_SEEK: /* 0x0a */
1663 if (result > 0)
1664 semihosting->result = 0;
1665 break;
1666 }
1667
1668 return semihosting->post_result(target);
1669 }
1670
1671 /**
1672 * Read all fields of a command from target to buffer.
1673 */
1674 static int semihosting_read_fields(struct target *target, size_t number,
1675 uint8_t *fields)
1676 {
1677 struct semihosting *semihosting = target->semihosting;
1678 /* Use 4-byte multiples to trigger fast memory access. */
1679 return target_read_memory(target, semihosting->param, 4,
1680 number * (semihosting->word_size_bytes / 4), fields);
1681 }
1682
1683 /**
1684 * Write all fields of a command from buffer to target.
1685 */
1686 static int semihosting_write_fields(struct target *target, size_t number,
1687 uint8_t *fields)
1688 {
1689 struct semihosting *semihosting = target->semihosting;
1690 /* Use 4-byte multiples to trigger fast memory access. */
1691 return target_write_memory(target, semihosting->param, 4,
1692 number * (semihosting->word_size_bytes / 4), fields);
1693 }
1694
1695 /**
1696 * Extract a field from the buffer, considering register size and endianness.
1697 */
1698 static uint64_t semihosting_get_field(struct target *target, size_t index,
1699 uint8_t *fields)
1700 {
1701 struct semihosting *semihosting = target->semihosting;
1702 if (semihosting->word_size_bytes == 8)
1703 return target_buffer_get_u64(target, fields + (index * 8));
1704 else
1705 return target_buffer_get_u32(target, fields + (index * 4));
1706 }
1707
1708 /**
1709 * Store a field in the buffer, considering register size and endianness.
1710 */
1711 static void semihosting_set_field(struct target *target, uint64_t value,
1712 size_t index,
1713 uint8_t *fields)
1714 {
1715 struct semihosting *semihosting = target->semihosting;
1716 if (semihosting->word_size_bytes == 8)
1717 target_buffer_set_u64(target, fields + (index * 8), value);
1718 else
1719 target_buffer_set_u32(target, fields + (index * 4), value);
1720 }
1721
1722 /* -------------------------------------------------------------------------
1723 * Semihosting redirect over TCP structs and functions */
1724
1725 static int semihosting_service_new_connection_handler(struct connection *connection)
1726 {
1727 struct semihosting_tcp_service *service = connection->service->priv;
1728 service->semihosting->tcp_connection = connection;
1729
1730 return ERROR_OK;
1731 }
1732
1733 static int semihosting_service_input_handler(struct connection *connection)
1734 {
1735 struct semihosting_tcp_service *service = connection->service->priv;
1736
1737 if (!connection->input_pending) {
1738 /* consume received data, not for semihosting IO */
1739 const int buf_len = 100;
1740 char buf[buf_len];
1741 int bytes_read = connection_read(connection, buf, buf_len);
1742
1743 if (bytes_read == 0) {
1744 return ERROR_SERVER_REMOTE_CLOSED;
1745 } else if (bytes_read == -1) {
1746 LOG_ERROR("error during read: %s", strerror(errno));
1747 return ERROR_SERVER_REMOTE_CLOSED;
1748 }
1749 } else if (service->error != ERROR_OK) {
1750 return ERROR_SERVER_REMOTE_CLOSED;
1751 }
1752
1753 return ERROR_OK;
1754 }
1755
1756 static int semihosting_service_connection_closed_handler(struct connection *connection)
1757 {
1758 struct semihosting_tcp_service *service = connection->service->priv;
1759 if (service) {
1760 free(service->name);
1761 free(service);
1762 }
1763
1764 return ERROR_OK;
1765 }
1766
1767 static void semihosting_tcp_close_cnx(struct semihosting *semihosting)
1768 {
1769 if (!semihosting->tcp_connection)
1770 return;
1771
1772 struct service *service = semihosting->tcp_connection->service;
1773 remove_service(service->name, service->port);
1774 semihosting->tcp_connection = NULL;
1775
1776 }
1777
1778 static const struct service_driver semihosting_service_driver = {
1779 .name = "semihosting",
1780 .new_connection_during_keep_alive_handler = NULL,
1781 .new_connection_handler = semihosting_service_new_connection_handler,
1782 .input_handler = semihosting_service_input_handler,
1783 .connection_closed_handler = semihosting_service_connection_closed_handler,
1784 .keep_client_alive_handler = NULL,
1785 };
1786
1787 /* -------------------------------------------------------------------------
1788 * Common semihosting commands handlers. */
1789
1790 COMMAND_HANDLER(handle_common_semihosting_command)
1791 {
1792 struct target *target = get_current_target(CMD_CTX);
1793
1794 if (!target) {
1795 LOG_ERROR("No target selected");
1796 return ERROR_FAIL;
1797 }
1798
1799 struct semihosting *semihosting = target->semihosting;
1800 if (!semihosting) {
1801 command_print(CMD, "semihosting not supported for current target");
1802 return ERROR_FAIL;
1803 }
1804
1805 if (CMD_ARGC > 0) {
1806 int is_active;
1807
1808 COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active);
1809
1810 if (!target_was_examined(target)) {
1811 LOG_ERROR("Target not examined yet");
1812 return ERROR_FAIL;
1813 }
1814
1815 if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) {
1816 LOG_ERROR("Failed to Configure semihosting");
1817 return ERROR_FAIL;
1818 }
1819
1820 /* FIXME never let that "catch" be dropped! (???) */
1821 semihosting->is_active = is_active;
1822 }
1823
1824 command_print(CMD, "semihosting is %s",
1825 semihosting->is_active
1826 ? "enabled" : "disabled");
1827
1828 return ERROR_OK;
1829 }
1830
1831 COMMAND_HANDLER(handle_common_semihosting_redirect_command)
1832 {
1833 struct target *target = get_current_target(CMD_CTX);
1834
1835 if (target == NULL) {
1836 LOG_ERROR("No target selected");
1837 return ERROR_FAIL;
1838 }
1839
1840 struct semihosting *semihosting = target->semihosting;
1841 if (!semihosting) {
1842 command_print(CMD, "semihosting not supported for current target");
1843 return ERROR_FAIL;
1844 }
1845
1846 if (!semihosting->is_active) {
1847 command_print(CMD, "semihosting not yet enabled for current target");
1848 return ERROR_FAIL;
1849 }
1850
1851 enum semihosting_redirect_config cfg;
1852 const char *port;
1853
1854 if (CMD_ARGC < 1)
1855 return ERROR_COMMAND_SYNTAX_ERROR;
1856
1857 if (strcmp(CMD_ARGV[0], "disable") == 0) {
1858 cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
1859 if (CMD_ARGC > 1)
1860 return ERROR_COMMAND_SYNTAX_ERROR;
1861 } else if (strcmp(CMD_ARGV[0], "tcp") == 0) {
1862 if (CMD_ARGC < 2 || CMD_ARGC > 3)
1863 return ERROR_COMMAND_SYNTAX_ERROR;
1864
1865 port = CMD_ARGV[1];
1866
1867 cfg = SEMIHOSTING_REDIRECT_CFG_ALL;
1868 if (CMD_ARGC == 3) {
1869 if (strcmp(CMD_ARGV[2], "debug") == 0)
1870 cfg = SEMIHOSTING_REDIRECT_CFG_DEBUG;
1871 else if (strcmp(CMD_ARGV[2], "stdio") == 0)
1872 cfg = SEMIHOSTING_REDIRECT_CFG_STDIO;
1873 else if (strcmp(CMD_ARGV[2], "all") != 0)
1874 return ERROR_COMMAND_SYNTAX_ERROR;
1875 }
1876 } else {
1877 return ERROR_COMMAND_SYNTAX_ERROR;
1878 }
1879
1880 semihosting_tcp_close_cnx(semihosting);
1881 semihosting->redirect_cfg = SEMIHOSTING_REDIRECT_CFG_NONE;
1882
1883 if (cfg != SEMIHOSTING_REDIRECT_CFG_NONE) {
1884 struct semihosting_tcp_service *service =
1885 calloc(1, sizeof(struct semihosting_tcp_service));
1886 if (!service) {
1887 LOG_ERROR("Failed to allocate semihosting TCP service.");
1888 return ERROR_FAIL;
1889 }
1890
1891 service->semihosting = semihosting;
1892
1893 service->name = alloc_printf("%s semihosting service", target_name(target));
1894 if (!service->name) {
1895 LOG_ERROR("Out of memory");
1896 free(service);
1897 return ERROR_FAIL;
1898 }
1899
1900 int ret = add_service(&semihosting_service_driver,
1901 port, 1, service);
1902
1903 if (ret != ERROR_OK) {
1904 LOG_ERROR("failed to initialize %s", service->name);
1905 free(service->name);
1906 free(service);
1907 return ERROR_FAIL;
1908 }
1909 }
1910
1911 semihosting->redirect_cfg = cfg;
1912
1913 return ERROR_OK;
1914 }
1915
1916 COMMAND_HANDLER(handle_common_semihosting_fileio_command)
1917 {
1918 struct target *target = get_current_target(CMD_CTX);
1919
1920 if (!target) {
1921 LOG_ERROR("No target selected");
1922 return ERROR_FAIL;
1923 }
1924
1925 struct semihosting *semihosting = target->semihosting;
1926 if (!semihosting) {
1927 command_print(CMD, "semihosting not supported for current target");
1928 return ERROR_FAIL;
1929 }
1930
1931 if (!semihosting->is_active) {
1932 command_print(CMD, "semihosting not yet enabled for current target");
1933 return ERROR_FAIL;
1934 }
1935
1936 if (CMD_ARGC > 0)
1937 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio);
1938
1939 command_print(CMD, "semihosting fileio is %s",
1940 semihosting->is_fileio
1941 ? "enabled" : "disabled");
1942
1943 return ERROR_OK;
1944 }
1945
1946 COMMAND_HANDLER(handle_common_semihosting_cmdline)
1947 {
1948 struct target *target = get_current_target(CMD_CTX);
1949 unsigned int i;
1950
1951 if (!target) {
1952 LOG_ERROR("No target selected");
1953 return ERROR_FAIL;
1954 }
1955
1956 struct semihosting *semihosting = target->semihosting;
1957 if (!semihosting) {
1958 command_print(CMD, "semihosting not supported for current target");
1959 return ERROR_FAIL;
1960 }
1961
1962 free(semihosting->cmdline);
1963 semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
1964
1965 for (i = 1; i < CMD_ARGC; i++) {
1966 char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]);
1967 if (!cmdline)
1968 break;
1969 free(semihosting->cmdline);
1970 semihosting->cmdline = cmdline;
1971 }
1972
1973 command_print(CMD, "semihosting command line is [%s]",
1974 semihosting->cmdline);
1975
1976 return ERROR_OK;
1977 }
1978
1979 COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
1980 {
1981 struct target *target = get_current_target(CMD_CTX);
1982
1983 if (!target) {
1984 LOG_ERROR("No target selected");
1985 return ERROR_FAIL;
1986 }
1987
1988 struct semihosting *semihosting = target->semihosting;
1989 if (!semihosting) {
1990 command_print(CMD, "semihosting not supported for current target");
1991 return ERROR_FAIL;
1992 }
1993
1994 if (!semihosting->is_active) {
1995 command_print(CMD, "semihosting not yet enabled for current target");
1996 return ERROR_FAIL;
1997 }
1998
1999 if (CMD_ARGC > 0)
2000 COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit);
2001
2002 command_print(CMD, "semihosting resumable exit is %s",
2003 semihosting->has_resumable_exit
2004 ? "enabled" : "disabled");
2005
2006 return ERROR_OK;
2007 }
2008
2009 COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
2010 {
2011 struct target *target = get_current_target(CMD_CTX);
2012 struct semihosting *semihosting = target->semihosting;
2013
2014 if (CMD_ARGC)
2015 return ERROR_COMMAND_SYNTAX_ERROR;
2016
2017 if (!semihosting->is_active) {
2018 LOG_ERROR("semihosting not yet enabled for current target");
2019 return ERROR_FAIL;
2020 }
2021
2022 if (!semihosting_user_op_params) {
2023 LOG_ERROR("This command is usable only from a registered user "
2024 "semihosting event callback.");
2025 return ERROR_FAIL;
2026 }
2027
2028 command_print_sameline(CMD, "%s", semihosting_user_op_params);
2029
2030 return ERROR_OK;
2031 }
2032
2033 COMMAND_HANDLER(handle_common_semihosting_basedir_command)
2034 {
2035 struct target *target = get_current_target(CMD_CTX);
2036
2037 if (CMD_ARGC > 1)
2038 return ERROR_COMMAND_SYNTAX_ERROR;
2039
2040 if (!target) {
2041 LOG_ERROR("No target selected");
2042 return ERROR_FAIL;
2043 }
2044
2045 struct semihosting *semihosting = target->semihosting;
2046 if (!semihosting) {
2047 command_print(CMD, "semihosting not supported for current target");
2048 return ERROR_FAIL;
2049 }
2050
2051 if (!semihosting->is_active) {
2052 command_print(CMD, "semihosting not yet enabled for current target");
2053 return ERROR_FAIL;
2054 }
2055
2056 if (CMD_ARGC > 0) {
2057 free(semihosting->basedir);
2058 semihosting->basedir = strdup(CMD_ARGV[0]);
2059 if (!semihosting->basedir) {
2060 command_print(CMD, "semihosting failed to allocate memory for basedir!");
2061 return ERROR_FAIL;
2062 }
2063 }
2064
2065 command_print(CMD, "semihosting base dir: %s",
2066 semihosting->basedir ? semihosting->basedir : "");
2067
2068 return ERROR_OK;
2069 }
2070
2071 const struct command_registration semihosting_common_handlers[] = {
2072 {
2073 .name = "semihosting",
2074 .handler = handle_common_semihosting_command,
2075 .mode = COMMAND_EXEC,
2076 .usage = "['enable'|'disable']",
2077 .help = "activate support for semihosting operations",
2078 },
2079 {
2080 .name = "semihosting_redirect",
2081 .handler = handle_common_semihosting_redirect_command,
2082 .mode = COMMAND_EXEC,
2083 .usage = "(disable | tcp <port> ['debug'|'stdio'|'all'])",
2084 .help = "redirect semihosting IO",
2085 },
2086 {
2087 .name = "semihosting_cmdline",
2088 .handler = handle_common_semihosting_cmdline,
2089 .mode = COMMAND_EXEC,
2090 .usage = "arguments",
2091 .help = "command line arguments to be passed to program",
2092 },
2093 {
2094 .name = "semihosting_fileio",
2095 .handler = handle_common_semihosting_fileio_command,
2096 .mode = COMMAND_EXEC,
2097 .usage = "['enable'|'disable']",
2098 .help = "activate support for semihosting fileio operations",
2099 },
2100 {
2101 .name = "semihosting_resexit",
2102 .handler = handle_common_semihosting_resumable_exit_command,
2103 .mode = COMMAND_EXEC,
2104 .usage = "['enable'|'disable']",
2105 .help = "activate support for semihosting resumable exit",
2106 },
2107 {
2108 .name = "semihosting_read_user_param",
2109 .handler = handle_common_semihosting_read_user_param_command,
2110 .mode = COMMAND_EXEC,
2111 .usage = "",
2112 .help = "read parameters in semihosting-user-cmd-0x10X callbacks",
2113 },
2114 {
2115 .name = "semihosting_basedir",
2116 .handler = handle_common_semihosting_basedir_command,
2117 .mode = COMMAND_EXEC,
2118 .usage = "[dir]",
2119 .help = "set the base directory for semihosting I/O operations",
2120 },
2121 COMMAND_REGISTRATION_DONE
2122 };

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)