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

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)