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

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)