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

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)