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

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)