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

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)